blob: 7ec6c28d8b70a394547ed0495476531e07004d8a [file] [log] [blame]
Zesstra83f011d2016-04-24 20:09:05 +02001/*
2
3 //TODO: implement retries
4 */
5
6#define protected public
7
8#pragma strict_types, save_types, rtt_checks, pedantic
9#pragma no_clone, no_shadow
10
11#include <tls.h>
12#include <config.h>
13#include <driver_info.h>
14#include <lpctypes.h>
15#include <strings.h>
16
17// data structures
18struct host_s {
19 string name;
20 string key;
21 string ip;
22 int port;
23 int last_contact;
24 int first_contact;
25 int reputation;
26 string *services;
27 int im_version;
28 int ncttl;
29 int mtu;
30 mapping received;
31};
32
33struct fragment_s {
34 string header;
35 string buf;
36};
37
38struct packet_s {
39 int id;
40 int timestamp;
41 int pversion;
42 int pflags;
43 struct fragment_s *fragments;
44 string peername;
45 mapping data;
46 string buf;
47};
48
49struct service_s {
50 string name;
51 string obname;
52 string fun;
53 closure recv_cb;
54};
55
56struct request_s {
57 int id;
58 struct packet_s packet;
59 closure callback;
60 int timeout;
61};
62
63// Prototypes & Defines
64protected void init();
65void ping_many_muds(string *muds);
66protected int calc_ncttl(struct host_s p);
67protected void send_helo(string name);
68
69// mud-compatibility layer - might implement efuns with lfuns if not available
70// on the specific mud.
71inherit __DIR__"inetd_compat";
72
73// Mapping of known peers with their names as keys.
74mapping peers = ([]);
75
76// our own offered services
77mapping services = ([]);
78
79// our own host_s structure - it also contains our _private_ key.
80struct host_s self = (<host_s>);
81
82// reset counter for housekeeping
83int reset_counter;
84
85nosave int last_packet_id = 0;
86nosave mapping requests = ([]);
87
88// Minimum protocol version to accept (default 0)
89int min_protocol_version = 0;
90
91// *** lfuns in this section might be re-defined to suit the individual muds.
92protected void debug_msg(string msg, int severity)
93{
94 write(msg);
95}
96
97protected void set_user()
98{
99 seteuid(getuid());
100}
101
102protected void save_me()
103{
104}
105
106protected int restore_me()
107{
108}
109
110protected void export_peer_list(mapping list)
111{
112}
113
114// *** end of mud-specific lfuns ***
115
116private string *sys_fields = ({HOST, NAME, PACKET, UDP_PORT, SYSTEM, VERSION,
117 FLAGS, SIGNATURE,
118 PACKET_LOSS, RESPONSE_TIME});
119
120// *** public interface
121public void register_service(string name, string fun)
122{
123 struct service_s serv;
124
125 closure cl = symbol_function(fun, previous_object());
126 if (!cl)
127 raise_error("register_service(): function not public.\n");
128
129 if (member(services, name))
130 serv = services[name];
131 else
132 serv = (<service_s>);
133
134 serv->name = name;
135 serv->obname = object_name(previous_object());
136 serv->fun = fun;
137 serv->recv_cb = cl;
138 services[name] = serv;
139 self->services = m_indices(services);
140 debug_msg(sprintf("Service registered: %O\n",serv),40);
141}
142
143public void unregister_service(string name)
144{
145 struct service_s serv = services[name];
146 if (!structp(serv))
147 return;
148 // wenn von aussen gerufen, nur registriertes Objekt selber.
149 if (extern_call() && serv->obname != object_name(previous_object()))
150 raise_error("Service can only be unregistered by service object.\n");
151 m_delete(services, name);
152 self->services = m_indices(services);
153 debug_msg(sprintf("Service unregistered: %s\n",name),40);
154}
155
156public string *QueryPeerList()
157{
158 return m_indices(peers);
159}
160
161// TODO: remove, for debug only
162public struct host_s QueryPeer(string name)
163{
164 return peers[name];
165}
166
167public string PeerName()
168{
169 return self->name;
170}
171
172// **************** internal implementation ***********************
173
174
175protected void configure_host(struct host_s new_self)
176{
177 new_self->first_contact = time();
178 new_self->last_contact = time();
179 new_self->reputation = __INT_MAX__;
180 new_self->ncttl = __INT_MAX__;
181 //if (!sizeof(new_self->services))
182 // raise_error("Illegal to configure peer without services!\n");
183 if(new_self->key)
184 new_self->im_version=2500;
185 else
186 new_self->im_version=2000;
187 if (new_self->mtu < 1024)
188 raise_error("The minimum UDP length (MTU) must >= 1024 bytes!\n");
189 // ok, uebernehmen
190 self = new_self;
191 debug_msg(sprintf("localhost configured: %O\n",self),30);
192}
193
194// Updates (or adds a new) peer.
195protected struct host_s add_new_peer(struct host_s p)
196{
197 // TODO: validate
198 // This must not happen, the caller must check for existence to prevent
199 // hijacking peer names...
200 if (member(peers, p->name))
201 raise_error("Attempt to add existing peer!\n");
202 if (p->mtu < 1024) p->mtu = 1024;
203 p->received = ([]);
204 peers[p->name] = p;
205 debug_msg(sprintf("new peer added: %O\n",p),50);
206 return p;
207}
208
209// Updates (or adds a new) peer.
210protected void update_peer(struct host_s p)
211{
212 //TODO validate
213 struct host_s old = peers[p->name];
214 if (!old)
215 peers[p->name] = p;
216 else
217 {
218 // we always keep some data...
219 old->key = p->key;
220 old->ip = p->ip;
221 old->port = p->port;
222 if (p->last_contact > old->last_contact)
223 old->last_contact = p->last_contact;
224 if (p->first_contact < old->first_contact)
225 old->first_contact = p->first_contact;
226 old->services=p->services;
227 old->reputation = p->reputation;
228 old->im_version = p->im_version;
229 if (p->mtu >= 1024) old->mtu = p->mtu;
230 old->ncttl = p->ncttl;
231 // keep packet fragments, don't update received.
232 debug_msg(sprintf("peer updated: %O\n",self),50);
233 }
234}
235
236// remove a peer from the known peer list
237protected void kill_peer(string name)
238{
239 m_delete(peers, name);
240 debug_msg(sprintf("peer deleteted: %s\n",name),50);
241}
242
243// Update last_contact value to current time.
244protected void touch_peer(string name)
245{
246 struct host_s p = peers[name];
247 if (p)
248 p->last_contact = time();
249}
250
251// imports old style host lists. Should only be done once.
252public int import_host_list(string file) {
253
254 int res;
255 mixed data = (read_file(file));
256 if (!data) {
257 debug_msg("*Error in reading host file: " + file +"\n\n", 100);
258 return 0;
259 }
260
261 data = old_explode(data, "\n");
262
263 foreach(string line: data)
264 {
265 if (line == "" || line[0] == '#')
266 continue;
267 mixed fields = old_explode(line, HOSTFILE_DEL);
268 if (sizeof(fields) < 5) {
269 debug_msg(sprintf(
270 "*Parse error in hosts file: %s, Line: %s\n", file, line), 100);
271 continue;
272 }
273
274 struct host_s p = (<host_s>);
275 p->name = lower_case(fields[HOSTLIST_NAME]);
276 // skip already known peers
277 if (member(peers, p->name))
278 continue; // mud already in list
279
280 p->services = old_explode(fields[HOSTLIST_LOCAL_COMMANDS],HOSTFILE_DEL2);
281 if (member(p->services,"*") != -1)
282 p->services = p->services - ({ "*" }) + DEFAULT_COMMANDS;
283 p->ip = fields[HOSTLIST_IP];
284 p->port = to_int(fields[HOSTLIST_UDP_PORT]);
285 // we fake first and last contact, otherwise it would be expired if not online.
286 p->first_contact = time();
287 p->last_contact = time();
288 p->mtu = 1024;
289 p->ncttl = calc_ncttl(p);
290
291 add_new_peer(p);
292 ++res;
293 }
294 debug_msg(sprintf("old-stype host list imported: %s, %d new peers\n",
295 file,res),50);
296 return res;
297}
298
299
300protected void init()
301{
302 if (!self)
303 raise_error("Can't init/startup without configuration!\n");
304
305 // Register the core services. Must be callother for previous_object being
306 // ourself
307 this_object()->register_service(PING, "recv_ping");
308 this_object()->register_service(QUERY, "recv_query");
309 this_object()->register_service(REPLY, "recv_reply");
310 this_object()->register_service(HELO, "recv_helo");
311 debug_msg(sprintf("init() performed, pinging known peers.\n"),30);
312 ping_many_muds(m_indices(peers));
313}
314
315protected string encode(mixed v)
316{
317 switch(typeof(v))
318 {
319 case T_NUMBER:
320 return to_string(v);
321 case T_STRING:
322 return "$"+v;
323 default:
324 // convert into a string representation - hopefully the receiver
325 // knows what to do with it.
326 return sprintf("$%Q",v);
327 }
328}
329
330#define SIGLENGTH 32+4 // length of signature including "$S:|"
331
332protected void sign_fragment(struct fragment_s f)
333{
334 if (self->key)
335 {
336 f->header=sprintf("%s$S:%s|", f->header,
337 hmac(TLS_HASH_SHA512, self->name, f->buf));
338 debug_msg(sprintf("signed fragment: %s, %s.\n",f->header,f->buf),90);
339 }
340 else
341 f->header="";
342}
343
344
345// creates a packet structure with fragments to send (can be only one, if the
346// packet does not need to be split).
347protected struct packet_s packetize(struct host_s dest, mapping data)
348{
349 // some field names in the packet are reserved and must not be used by
350 // users, they are added by the inetd.
351 if (sizeof(data & sys_fields))
352 raise_error(sprintf(
353 "Data must not contain reserved system fields: %O.\n",
354 data & sys_fields));
355
356 // create packet structure
357 struct packet_s packet = (<packet_s>
358 id: ++last_packet_id, timestamp: time(),
359 pversion: self->im_version, pflags: 0,
360 fragments: 0, peername: 0, data: data, buf: 0);
361
362 // add the system fields (NAME, V, F must be the first fields!)
363 // the ID field is special, because maybe the packet is an answer to a
364 // request. In this case, we must keep the original ID
365 if (!member(data, ID))
366 data[ID] = packet->id;
367 else
368 {
369 if (data[REQUEST] != REPLY)
370 raise_error(sprintf("ID only permitted in reply packets!"));
371 }
372 // NAME is added below
373 data[UDP_PORT] = self->port;
374
375 // create an array of fields (key:value pairs)
376 string data_field;
377 string * fields = allocate(sizeof(data)+3);
378 fields[0] = sprintf("NAME:%s", self->name);
379 fields[1] = sprintf("V:%d", packet->pversion);
380 fields[2] = sprintf("F:%d", packet->pflags);
381 int cindex = 3;
382 foreach(string key, mixed val : data)
383 {
384 // the DATA field must be added last, so remember its encoded string.
385 // Also, it is not checked for reserved characters
386 if (key == DATA)
387 data_field = sprintf("%s:%s", encode(DATA), encode(val));
388 else
389 {
390 if (!stringp(key) || !sizeof(key))
391 raise_error(sprintf("send((): Illegal field name %.30O in data "
392 "payload.\n",key));
393 string ekey = encode(key);
394 string eval = encode(val);
395 // check key and value strings for reserved characters
396 if (regmatch(ekey,"[|:]") || regmatch(eval, "[|:]"))
397 raise_error(sprintf("send(): Field name or value contains reserved "
398 "character: %.50s,%.50s\n", ekey, eval));
399 fields[cindex] = sprintf("%s:%s",ekey,eval);
400 ++cindex;
401 }
402 }
403 // add the DATA field if existing
404 if (data_field)
405 fields[cindex] = data_field;
406
407 // write the string buffer
408 packet->buf = implode(fields, "|");
409
410 // now split into fragments if packet too large for one.
411 int mtu = min(self->mtu, dest->mtu);
412 if ((mtu - SIGLENGTH - sizeof(packet->buf)) < 0)
413 {
414 // multiple fragments, each starting with
415 // PKT:peername:packet-id:packet-number/total-packets|
416 // fsize is the maximum payload length per fragment.
417 string fheader = sprintf("PKT:%s:%d:", self->name, packet->id);
418 int fsize = mtu - SIGLENGTH - sizeof(fheader)
419 - 8; // sizeof("nnn/mmm|")
420 string buffer = packet->buf;
421 int fcount = sizeof(buffer) / fsize;
422 // if there is a modulo left, we need one additional fragment
423 if (sizeof(buffer) % fsize)
424 ++fcount;
425 if (fcount > 999) // too many fragments?
426 raise_error("packet too long to send.\n");
427 // allocate the complete fragment array.
428 packet->fragments = allocate(fcount);
429 foreach(int i: fcount)
430 {
431 struct fragment_s f = (<fragment_s>
432 header:sprintf("%s%d/%d|",fheader,i+1,fcount),
433 buf: buffer[i*fsize .. min((i+1)*fsize, sizeof(buffer))-1]
434 );
435 sign_fragment(f);
436 packet->fragments[i] = f;
437 debug_msg(sprintf("Created fragment %d/%d\n", i,fcount),90);
438 }
439 }
440 else
441 {
442 // one fragment, and the fragment header will be empty.
443 struct fragment_s f = (<fragment_s> header: "",
444 buf: packet->buf);
445 sign_fragment(f);
446 packet->fragments = ({f});
447 debug_msg(sprintf("Created fragment 1/1\n"),90);
448 }
449 return packet;
450}
451
452// encodes the mapping data into a packet and sends it to <dest>. The
453// key-value pairs of <data> are converted into intermud fields. The keys must
454// be strings and only the DATA field can contain : or |.
455// Also, <data> must not contain any reserved field names.
456// If the caller expects an answer, <cb> must contain a calleable closure. In
457// this case, the inetd remembers the request. When the answer arrives, the
458// callback <cb> is called with the request id (int) and a mapping (the answer
459// packet) as arguments. The return value of send() is in this case the
460// request id used for storage.
461// <= 0 for error, > 0 for success.
462public int send(string dest, mapping data, closure cb)
463{
464 if (!sizeof(data))
465 raise_error("Illegal sending empty packets.");
466 if (!sizeof(dest))
467 raise_error("Can't send without destination: %O.\n");
468 // find peer data. If not found, abort and tell the caller
469 struct host_s peer = peers[dest];
470 if (!structp(peer))
471 return -1;
472
473 if (member(peer->services, data[REQUEST]) == -1)
474 raise_error("Remote host doesn't offer service "+
475 data[REQUEST] + ".\n");
476
477 // then packetize the data, i.e. create packet structure, encode into buffer
478 // and split into fragments as needed and sign fragments.
479 // There will be at least one fragment structure.
480 struct packet_s packet = packetize(peer, data);
481
482 // loop over all fragments and send them
483 foreach(struct fragment_s f : packet->fragments)
484 {
485 debug_msg(sprintf("%O <- %.500O\n",peer->ip, f->header + f->buf), 100);
486 // TODO: error handling
487 send_udp(peer->ip, peer->port, f->header + f->buf);
488 }
489 // delete the buffer
490 packet->buf = 0;
491 // delete the fragments until we support re-transmission of fragments
492 packet->fragments = 0;
493
494 // we keep the original data for reference, if storing the request.
495
496 // if an answer is expected, there is a callback closure. Then we store the
497 // request with a timeout of 120s.
498 if (cb)
499 {
500 struct request_s r = (<request_s> packet->id, packet, cb, time()+120);
501 requests[r->id] = r;
502 debug_msg(sprintf("Answer expected, request stored\n"),80);
503 }
504
505 return packet->id;
506}
507
508// like send(), but sends to all peers offering the service <service>. But
509// limited to peers we had contact with in the last 24h.
510public int broadcast(string service, mapping data, closure cb)
511{
512 if (!service)
513 raise_error("No service given!\n");
514 if (!sizeof(data))
515 raise_error("Illegal sending empty packets.");
516//TODO: check if we could send the same packet to all peers, instead of
517//packetizing for each peer as well.
518 int ret;
519 int tlc_cutoff = time() - 86400;
520 foreach(string dest, struct host_s peer : peers)
521 {
522 if (peer->last_contact >= tlc_cutoff
523 && member(peer->service, service) != -1)
524 {
525 send(dest, data, cb);
526 ++ret;
527 }
528 }
529 return ret;
530}
531
532protected string|int decode(string arg)
533{
534 if (sizeof(arg) && arg[0] == '$')
535 return arg[1..];
536 if (to_string(to_int(arg)) == arg)
537 return to_int(arg);
538
539 return arg;
540}
541
542// must be validated before. Parses the packet buffer into the given packet
543// structure and returns it. In case of errors (e.g. malformed packets), 0 is
544// returned.
545protected struct packet_s parse_packet(struct packet_s packet)
546{
547 string *fields = explode(packet->buf, "|");
548 // The DATA field may contain any number of | which don't signify a field.
549 // Therefore counting | over-estimates the number of fields. To prevent
550 // excessive memory allocation, we limit the allocation to 32 fields. The
551 // mapping may still grow if there are really more fields.
552 packet->data = m_allocate(min(sizeof(fields),32));
553 int cindex;
554 while (cindex < sizeof(fields))
555 {
556 string header, info;
557 /// DATA fields can be denoted by a preceeding blank field :-/
558 if (!sizeof(fields[cindex]))
559 {
560 ++cindex;
561 header = DATA;
562 //Test for illegal packet length (no DATA)
563 if (cindex >= sizeof(fields))
564 return 0;
565 // take the first "field" of DATA (the rest is added below)
566 info = fields[cindex];
567 }
568 else if (sscanf(fields[cindex], "%s:%s", header, info) != 2)
569 return 0;
570 header = decode(header);
571 if (header == DATA)
572 {
573 // add the rest of the packet and combine back into one string if
574 // necessary
575 if (cindex < sizeof(fields)-1)
576 info = implode(({info}) + fields[cindex+1 ..], "|");
577 // and we have finished after decoding info
578 cindex = sizeof(fields);
579 }
580 packet->data[header] = decode(info);
581 ++cindex;
582 }
583 // only allow printable characters for these fields.
584 response[SENDER] =
585 regreplace(response[SENDER],"[:^print:]|\n","",1);
586 response[NAME] =
587 regreplace(response[NAME],"[:^print:]|\n","",1);
588 response[RECIPIENT] =
589 regreplace(response[RECIPIENT],"[:^print:]|\n","",1);
590
591 return packet;
592}
593
594protected void defragment_packet(struct packet_s p)
595{
596 if (sizeof(p->fragments))
597 {
598 p->buf = "";
599 foreach(struct fragment_s f : p->fragments)
600 {
601 p->buf += f->buf;
602 }
603 p->fragments = 0;
604 }
605}
606
607protected int validate_signature(string signature, string buf, struct host_s src)
608{
609 if (!src->key)
610 return 0;
611 // TODO: debug purpose
612 return 1;
613}
614
615// returns a packet_s or 0 for invalid or incomplete (!) packet. In both
616// cases, the caller should not do anything. In case of incomplete packets,
617// the fragment will be stored, if it was valid.
618protected struct packet_s validate_fragment(string buffer, struct host_s sender)
619{
620 string signature, pname;
621 int packetid, fragno, totalfrags, version, flags;
622 struct packet_s packet;
623 struct fragment_s f;
624
625 if (sizeof(buffer) > MAX_UDP_LENGTH)
626 return 0;
627
628 if (sscanf(buffer, "S:%s|NAME:%s|V:%d|$F:%d|%~s",
629 signature, pname, version, flags) == 5)
630 {
631 // non-fragmented v2.5+ packet
632 debug_msg(sprintf("Received v2.5+ packet.\n"),90);
633 pname = lower_case(pname);
634 packet = (<packet_s> timestamp: time(), pversion: version,
635 pflags: (flags & ~FL_VALID_SIGNATURE),
636 buf: buffer[strstr(buffer,"|")+1..]
637 );
638 debug_msg(sprintf("Received v2.5+ packet from %s.\n",pname),90);
639 sender = peers[pname];
640 // if we don't know the sender yet, we create a new peer with its name.
641 // The ip and port will be updated during parsing.
642 if (!sender)
643 {
644 sender = add_new_peer( (<host_s> name: pname,
645 first_contact: time(),
646 last_contact: time(),
647 mtu: 1024,
648 im_version : version,
649 received: m_allocate(5)
650 ));
651 // but if we can't create one, we discard the packet
652 if (!sender)
653 return 0;
654 }
655 packet->peername = pname;
656 // try to check the packet signature and record the result, if
657 // successful.
658 if (validate_signature(signature, packet->buf, sender))
659 {
660 packet->pflags |= FL_VALID_SIGNATURE;
661 }
662 }
663 else if (sscanf(buffer, "PKT:%.1s:%d:%d/%d|%~s",
664 pname, packetid, fragno, totalfrags) == 5)
665 {
666 // this is a fragmented packet
667 // we at least check if the info about fragmentation is sane.
668 if (totalfrags > 999 || fragno > totalfrags
669 || totalfrags < 1 || fragno < 1)
670 return 0;
671
672 pname=lower_case(pname);
673
674 // is it even a IM 2.5+ packet? (want to avoid copying the buffer,
675 // therefore this approach)
676 if (sscanf(buffer, "PKT:%.1~s:%~d:%~d/%~d|$S:%.10s|%~s",
677 signature) == 6)
678 {
679 // create fragment (we know, there are at least two |)
680 int first_pipe = strstr(buffer,"|");
681 int sig_end = strstr(buffer, "|", first_pipe+1);
682 f = (<fragment_s> header: buffer[0..first_pipe],
683 buf: buffer[sig_end+1 ..]
684 );
685 debug_msg(sprintf("Received v2.5+ packet %d, fragment %d/%d from %s.\n"
686 ,packetid, fragno, totalfrags, pname),90);
687 }
688 else
689 {
690 // create fragment (we know, there is at least one |)
691 debug_msg(sprintf("Received v2 packet %d, fragment %d/%d from %s.\n"
692 ,packetid, fragno, totalfrags, pname),90);
693 int header_end = strstr(buffer, "|");
694 f = (<fragment_s> header: buffer[0..header_end],
695 buf: buffer[header_end+1 ..]
696 );
697 }
698
699 // get the sender
700 sender = peers[pname];
701 // if we don't know the sender yet, we create a new peer with its name.
702 // The ip and port will be updated during parsing, when the packet is
703 // complete.
704 if (!sender)
705 {
706 // if we can't create one, we discard the fragment
707 sender = add_new_peer( (<host_s> name: pname,
708 first_contact: time(),
709 last_contact: time(),
710 mtu: 1024,
711 received: m_allocate(5)
712 ));
713 if (!sender)
714 return 0;
715 }
716 // did we already received a fragment? - get its packet
717 packet = sender->received[packetid];
718 // if not create new packet structure and add it to the receive queue of
719 // the peer
720 if (!packet)
721 {
722 packet = (<packet_s> id : packetid, timestamp: time(),
723 peername: pname,
724 fragments : allocate(totalfrags, 0)
725 );
726 m_add(sender->received, packetid, packet);
727 }
728
729 // now we can also check the signature, if there is one.
730 if (signature &&
731 validate_signature(signature, f->header+f->buf, sender))
732 {
733 packet->pflags |= FL_VALID_SIGNATURE;
734 }
735 else
736 {
737 // if there is no valid signature, but we received a fragment of this
738 // packet with valid signature, we discard the fragment.
739 if (packet->pflags & FL_VALID_SIGNATURE)
740 {
741 debug_msg(sprintf("Received fragment %d with invalid signature in "
742 "signed packet %d from %s. Discarding fragment.\n"
743 ,fragno, packetid, pname),40);
744 return 0;
745 }
746 }
747
748 // add fragment to its slot - if we receive a fragment twice, the last one
749 // arriving wins.
750 packet->fragments[fragno] = f;
751 // if not all fragments are received, we end processing here and wait for
752 // more.
753 if (member(packet->fragments, 0))
754 return 0;
755 }
756 else
757 {
758 // we assume a non-fragmented legacy packet, no real validation
759 // possible.
760 packet = (<packet_s> timestamp: time(),
761 buf: buffer
762 );
763
764 debug_msg(sprintf("Received v2 packet.\n"),90);
765 }
766 // at this point we have a complete packet - but we may have to defragment
767 // it yet.
768 if (packet->fragments)
769 {
770 defragment_packet(packet);
771 // and remove it from the receive queue of the sender (note, if we have
772 // fragments in the packet, we also have a valid sender at this point)
773 m_delete(sender->received, packet->id);
774 // and check for versions and flags - will be there for IM 2.5+ packets.
775 // Note: if the sender claims a version < 2000 here, this is also fine.
776 // If not there, we assume IM 2/Zebedee.
777 if (sscanf(buffer, "NAME:%~s|V:%d|$F:%d|%~s",
778 version, flags) == 4)
779 {
780 packet->pversion = version;
781 // store flags, but do not set the FL_VALID_SIGNATURE flag ;-)
782 packet->pflags |= (flags & ~FL_VALID_SIGNATURE);
783 }
784 else
785 packet->pversion = 2000;
786 }
787
788 // if the packet has a version >= 2500, it must be signed. If not, we
789 // discard it.
790 if (packet->pversion >= 2500
791 && !(packet->pflags & FL_VALID_SIGNATURE))
792 {
793 // But there is one exception: if we don't have a key for the
794 // peer yet, we accept the packet anyway. This is needed to receive its
795 // public key, which we are going to ask them (soon).
796 if (sender->key)
797 {
798 debug_msg(sprintf("Received unsigned packet from v2.5+ peer with "
799 "key. Discarding."),40);
800 return 0; // key, but no valid signature - discard it.
801 }
802 }
803
804 // Maybe we accept only packets conforming to a specific protocol version
805 // (or newer). This can be used to accept only signated packets.
806 // also we don't accept protocol version older than we already saw for this
807 // peer to prevent downgrade attacks
808 if (packet->pversion < min_protocol_version)
809 return 0;
810
811 return packet;
812}
813
814/* Check wether a UDP request was valid. Is done after validating and parsing
815 * the packet (and all its fragments).
816 * Logs are made and "host" information is updated as appropriate.
817 * Arguments: Decoded UDP packet (struct packet_s)
818 * sending peer (struct host_s)
819 * Returns: 0 for valid packets, an erro r string otherwise.
820 */
821string validate_request(struct packet_s p, struct host_s sender)
822{
823 // If we have no peername, it was a legacy packet. Try to find the NAME in
824 // the packet payload.
825 if (!p->peername)
826 {
827 if(!member(p->data, NAME))
828 return "Name of sending peer not given.\n";
829 p->peername = lower_case(p->data[NAME]);
830 }
831
832 if (p->peername == self->name)
833 return "Someone tried to fake ourself!\n";
834
835 // if needed, check the payload for the ID. The ID may be absent...
836 if (!p->id)
837 p->id = p->data[ID];
838 // ... unless this is a reply to a request. And also, a reply can only be
839 // valid, when know about the initial request sent by us.
840 struct request_s req;
841 if (p->data[REQUEST] == REPLY)
842 {
843 if (!p->id)
844 return "Reply packet without packet ID.\n";
845 // and we take note of the request while we are at it, in case we need it.
846 req = requests[p->id];
847 if (!structp(req))
848 return "Reply packet without request.\n";
849 }
850
851 // if we still have no sender (legacy non-fragmented packets), we finally
852 // create one, because we know the sender by name now.
853 sender = peers[p->peername];
854 if (!sender)
855 {
856 // but if we can't create one, we discard the request
857 sender = add_new_peer( (<host_s> name: p->peername,
858 first_contact: time(),
859 last_contact: time(),
860 mtu: 1024,
861 received: m_allocate(3),
862 ));
863 if (!sender)
864 return "New peer, but peer list too full.\n";
865 }
866
867 // we don't accept protocol version older than we already saw for this
868 // peer to prevent downgrade attacks.
869 if (p->pversion < sender->im_version)
870 return "Downgraded peer intermud version.";
871 else
872 sender->im_version = p->pversion;
873
874 // if we have a packet with version >= 2500 and no key for the peer
875 // yet, we ask them by sending a HELO packet (which also transmits our
876 // public key).
877 // Note: if we have a packet with version >= 2500, no valid signature, but
878 // already a key for the peer, validate_fragment() would already have
879 // discarded the packet/fragment and we would not be here.
880 // Of course, don't HELO, if this is a helo.
881 if (p->pversion >= 2500 && !sender->key
882 && p->data[REQUEST] != HELO)
883 {
884 // also don't HELO, if this is a response to a HELO...
885 if (!req || req->packet->data[REQUEST] != HELO)
886 send_helo(p->peername);
887 }
888
889 // Note: HELO packets or HELO reponses in packets without valid signature
890 // can't survive until here if we know a key for the peer. Therefore, we
891 // don't have to validate that specifically.
892
893 // TODO: e.g. some requests are allowed only in signed packets.
894
895 return 0; // request ok!
896}
897
898// processes the received packet or fragment. Must be called from the
899// function called by the mudlib master in this object.
900protected void process_fragment(string host, string msg, int hostport)
901{
902 // Catch if someone tries to fake ourself.
903 if (host == self->ip && hostport == self->port)
904 return;
905 debug_msg(sprintf("Received packet from %s:%d.\n",
906 host, hostport), 100);
907 // First (try to) validate the received fragment (or packet).
908 struct host_s sender;
909 struct packet_s p = validate_fragment(msg, &sender);
910 // If we got a packet structure, the packet is complete and all the
911 // fragments were valid. If not, the packet is either invalid (and to be
912 // discarded) or not complete yet. In both cases, processing ends here.
913 if (!p)
914 return;
915
916 // first parse the packet into a mapping. And again, when not successful,
917 // 0 will be returned.
918 p = parse_packet(p);
919 if (!p)
920 return;
921
922 // record sending host data, may be important for validating the request.
923 p->data[HOST] = host;
924 p->data[UDP_PORT] = hostport;
925
926 debug_msg(sprintf("Packet valid and complete.\n"), 90);
927
928 // Validate the request...
929 string reason = validate_request(p, &sender);
930 if (reason)
931 {
932 debug_msg("validate_request(): discarding request: "+reason+"\n", 30);
933 return; //discard
934 }
935 sender->last_contact = time();
936 // if we received the packet from a host/port combination that is different
937 // from the one we know for this peers, we update the ip address and port.
938 // Note: if the packet was signed, the origin is proved by now. If not...
939 // well... We believe it now.
940 if (sender->ip != host || sender->port != hostport)
941 {
942 debug_msg(sprintf("Updating address of peer %s from %s:%d to %s:%d.\n",
943 sender->name, sender->ip, sender->port,
944 host, hostport), 40);
945 sender->ip = host;
946 sender->port = hostport;
947 }
948
949 touch_peer(sender->name);
950
951 // then execute/forward it.
952 struct service_s srv = services[p->data[REQUEST]];
953 if (srv)
954 {
955 if (!srv->recv_cb)
956 {
957 srv->recv_cb = symbol_function(srv->fun, find_object(srv->obname));
958 if (!srv->recv_cb)
959 {
960 // If no callable, the service is unregistered.
961 unregister_service(srv->name);
962 return;
963 }
964 }
965 funcall(srv->recv_cb, p->data);
966 }
967 else
968 // unknown service. Discard for now. //TODO:: send reply
969 return;
970
971} // process_fragment()
972
973
974// returns an increase in reputation (may be 0),
975// may be overloaded in inheritees.
976protected int auto_promote_peer(struct host_s p)
977{
978 // only if we heard from that peer in the last day.
979 if (p->last_contact + 86400 < time())
980 return 0;
981 // TODO: decide if auto-promotion above n should be tied to having a key.
982 if (p->reputation < 1
983 && p->first_contact < time() - 7*86400)
984 return 1;
985 if (p->reputation < 2
986 && p->first_contact < time() - 30*86400)
987 return 1;
988 if (p->reputation < 3
989 && p->first_contact < time() - 12*30*86400)
990 return 1;
991
992 return 0;
993}
994
995// Calculate the not-connected-time-to-live depending on the reputation. May
996// be overloaded in inheritees.
997protected int calc_ncttl(struct host_s p)
998{
999 switch(p->reputation)
1000 {
1001 case 0:
1002 return 3*86400;
1003 case 1:
1004 return 14*86400;
1005 case 2:
1006 return 3*30*86400;
1007 case 3:
1008 return 6*30*86400;
1009 default:
1010 return 12*30*86400;
1011 }
1012}
1013
1014// checks if a peer should be expired (forgotten) and deletes it from our
1015// known peer list if necessary.
1016protected int check_and_delete_peer(struct host_s peer)
1017{
1018 if (peer->last_contact + peer->ncttl < time())
1019 {
1020 m_delete(peers, peer->name);
1021 }
1022}
1023
1024void reset()
1025{
1026 set_next_reset(600);
1027 // housekeeping of peer list every 60 resets (6h).
1028 reset_counter = ++reset_counter % 60;
1029
1030 // expire stale requests
1031 foreach(int id, struct request_s r : requests)
1032 {
1033 if (r->timeout < time())
1034 {
1035 // in case of timeouts we call the callback, but with no data
1036 funcall(r->callback, id, r->packet->data, 0);
1037 m_delete(requests, id);
1038 }
1039 }
1040
1041 // peer housekeeping: increse reputation, expire peers
1042 // expire fragments in all peers
1043 foreach(string name, struct host_s peer : peers)
1044 {
1045 // should we do housekeeping of peer list?
1046 if (!reset_counter)
1047 {
1048 // first check if peer should be expired, because we had no contact for an
1049 // extended time.
1050 if (check_and_delete_peer(peer))
1051 continue;
1052 // check if the reputation of a peer can be auto-promoted
1053 peer->reputation += auto_promote_peer(peer);
1054 peer->ncttl = calc_ncttl(peer);
1055 }
1056
1057 if (!mappingp(peer->received) || !sizeof(peer->received))
1058 continue;
1059
1060 // check all incomplete fragments
1061 foreach(int id, struct packet_s pack : peer->received)
1062 {
1063 if (pack->timestamp + 120 < time())
1064 m_delete(peer->received, id);
1065 //TODO: send info to sender?
1066 }
1067 }
1068}
1069
1070// *** Core services every implementation must have.
1071
1072// we received a reply to one of our pings
1073protected void recv_ping_reply(int id, mapping request, mapping response)
1074{
1075 //TODO: what should we do?
1076}
1077
1078// we received a ping request
1079protected void recv_ping(mapping data)
1080{
1081 send(data[NAME], ([ID: data[ID], REQUEST:REPLY,
1082 DATA: self->name +" is alive!\n"]), 0);
1083}
1084
1085// sends a ping request to a peer
1086protected void send_ping(string mud)
1087{
1088 send(mud, ([ REQUEST: PING ]), #'recv_ping_reply);
1089}
1090
1091// We received a reply for one of our QUERY requests.
1092protected void recv_query_reply(int id, mapping request, mapping response)
1093{
1094 //TODO: what do we do with the information?
1095}
1096
1097// send a query request asking for <prop>
1098public void send_query(string name, string prop)
1099{
1100 if (!stringp(name) || !stringp(prop))
1101 return;
1102 send(name, ([REQUEST: QUERY, DATA: prop,
1103 SENDER: getuid(previous_object()) ]), #'recv_query_reply);
1104}
1105
1106// we received a reply request.
1107protected void recv_query(mapping data)
1108{
1109 mapping ret;
1110 switch(data[DATA])
1111 {
1112 case "commands":
1113 ret = ([DATA: implode(self->services, ":") ]);
1114 break;
1115 case "email":
1116 ret = ([DATA: EMAIL]);
1117 break;
1118 case "hosts":
1119 string tmp="";
1120 foreach(struct host_s p : peers)
1121 {
1122 tmp += p->name + ":" + p->ip + ":" + p->port
1123 + ":" + implode(p->services, ",") + ":" +
1124 implode(p->services, ",") + "\n";
1125 }
1126 ret = ([DATA: trim(tmp, TRIM_RIGHT, "\n") ]);
1127 break;
1128 case "inetd":
1129 case "version":
1130 ret = ([DATA: self->im_version ]);
1131 break;
1132 case "list":
1133 ret = ([DATA: "commands,email,hosts,inetd,version,mud_port" ]);
1134 break;
1135 case "mud_port":
1136 ret = ([DATA: query_mud_port() ]);
1137 break;
1138 case "time":
1139 ret = ([DATA: time()]);
1140 break;
1141 default:
1142 return; // Just ignore request for the time being.
1143 }
1144 ret[REQUEST] = REPLY;
1145 ret[RECIPIENT] = data[SENDER];
1146 ret[ID] = data[ID];
1147 ret["QUERY"] = data[DATA]; //TODO: this is not right, right?
1148
1149 send(data[NAME], ret, 0);
1150}
1151
1152// Called, when we receive a reply of OUR HELO request.
1153protected void recv_helo_reply(int id, mapping request, mapping response)
1154{
1155 struct host_s peer = peers[response[NAME]];
1156 // if we already have a key for the peer, we accept data and answer only if
1157 // the packet was correctly signed. Although the check should be redundant,
1158 // because then the packet should have been discarded earlier. But for this,
1159 // better safe, than sorry.
1160 if (peer->key
1161 && !(response[FLAGS] & FL_VALID_SIGNATURE))
1162 raise_error("Unexpected unsigned packed from "
1163 + peer->name + ".\n");
1164
1165 mapping theirinfo = json_parse(response[DATA]);
1166 // yes - this is a way to update a key... Sending a HELO packet signed
1167 // with the old key
1168 peer->key = response["pkey"];
1169 if (response["mtu"] >= 1024)
1170 peer->mtu = min(response["mtu"], MAX_UDP_LENGTH);
1171 if (pointerp(data["services"]))
1172 peer->services = data["services"];
1173}
1174
1175// we received a HELO packet, send back our info.
1176protected void recv_helo(mapping data)
1177{
1178 struct host_s peer = peers[data[NAME]];
1179 // if we already have a key for the peer, we accept data and answer only if
1180 // the packet was correctly signed. Although the check should be redundant,
1181 // because then the packet should have been discarded earlier. But for this,
1182 // better safe, than sorry.
1183 if (peer->key
1184 && !(data[FLAGS] & FL_VALID_SIGNATURE))
1185 raise_error("Unexpected unsigned packed from "
1186 + peer->name + ".\n");
1187
1188 mapping theirinfo = json_parse(data[DATA]);
1189 // yes - this is a way to update a key... Sending a HELO packet signed
1190 // with the old key
1191 peer->key = theirinfo["pkey"];
1192 if (theirinfo["mtu"] >= 1024)
1193 peer->mtu = min(theirinfo["mtu"], MAX_UDP_LENGTH);
1194 if (pointerp(theirinfo["services"]))
1195 peer->services = theirinfo["services"];
1196
1197 mapping ourinfo = (["mtu": self->mtu, "pkey": self->key,
1198 "services": self->services ]);
1199 send(data[NAME], ([ID: data[ID], REQUEST:REPLY,
1200 DATA: json_serialize(ourinfo) ]), 0 );
1201}
1202
1203// send a HELO packet.
1204protected void send_helo(string name)
1205{
1206 mapping ourinfo = (["mtu": self->mtu, "pkey": self->key,
1207 "services": self->services]);
1208 send(name, ([REQUEST:HELO,
1209 DATA: json_serialize(ourinfo) ]), #'recv_helo_reply );
1210}
1211
1212// We received some reply for one of our requests - find our initial request
1213// and forward the data to the callback.
1214protected void recv_reply(mapping data)
1215{
1216 // validate_request ensured that we have the initial request.
1217 int pid = data[ID];
1218 debug_msg(sprintf("Received answer for request %d\n",pid),90);
1219 struct request_s req = requests[pid];
1220 m_delete(requests, pid);
1221 funcall(req->callback, pid, req->packet->data, data);
1222}
1223
1224/*
1225 * Make a PING request to all muds in the "hosts" mapping to set
1226 * HOSTLIST_STATUS information.
1227 * But don't ping all muds at once, because that may overflow the callout
1228 * table during mud startup, when hundreds of objects make callouts.
1229 */
1230void ping_many_muds(string *muds)
1231{
1232 if (!pointerp(muds))
1233 muds=m_indices(peers);
1234 if (!sizeof(muds))
1235 return;
1236 string *part;
1237 if (sizeof(muds) > 9)
1238 part=muds[0..9];
1239 else
1240 part=muds;
1241 foreach(string mud: part)
1242 send_ping(mud);
1243 muds -= part;
1244 if (sizeof(muds))
1245 call_out(#'ping_many_muds, 4, muds);
1246}
1247
1248protected void create()
1249{
1250 if (object_name(this_object()) == __FILE__[0..<3])
1251 {
1252 set_next_reset(-1);
1253 return;
1254 }
1255 set_user();
1256 restore_me();
1257 init();
1258}
1259
1260protected void create_super()
1261{
1262 set_next_reset(-1);
1263}
1264
1265int remove(int silent)
1266{
1267 reset();
1268 save_me();
1269 destruct(this_object());
1270 return 1;
1271}
1272