Changes to p2pd for duplicate packet filter
[olsrd.git] / lib / secure / src / olsrd_secure.c
1
2 /*
3  * Secure OLSR plugin
4  * http://www.olsr.org
5  *
6  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  *   notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright
16  *   notice, this list of conditions and the following disclaimer in
17  *   the documentation and/or other materials provided with the
18  *   distribution.
19  * * Neither the name of olsrd, olsr.org nor the names of its
20  *   contributors may be used to endorse or promote products derived
21  *   from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37
38 /*
39  * Dynamic linked library for the olsr.org olsr daemon
40  */
41
42 #include "olsrd_secure.h"
43
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #include <signal.h>
50
51 #include "defs.h"
52 #include "ipcalc.h"
53 #include "olsr.h"
54 #include "parser.h"
55 #include "scheduler.h"
56 #include "net_olsr.h"
57
58 #ifdef USE_OPENSSL
59
60 /* OpenSSL stuff */
61 #include <openssl/sha.h>
62
63 #define CHECKSUM SHA1
64 #define SCHEME   SHA1_INCLUDING_KEY
65
66 #else
67
68 /* Homebrewn checksuming */
69 #include "md5.h"
70
71 static void
72 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
73 {
74   MD5_CTX context;
75
76   MD5Init(&context);
77   MD5Update(&context, data, data_len);
78   MD5Final(hashbuf, &context);
79 }
80
81 #define CHECKSUM MD5_checksum
82 #define SCHEME   MD5_INCLUDING_KEY
83
84 #endif
85
86 #ifdef OS
87 #undef OS
88 #endif
89
90 #ifdef WIN32
91 #define close(x) closesocket(x)
92 #undef EWOULDBLOCK
93 #define EWOULDBLOCK WSAEWOULDBLOCK
94 #define OS "Windows"
95 #endif
96 #ifdef linux
97 #define OS "GNU/Linux"
98 #endif
99 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
100 #define OS "FreeBSD"
101 #endif
102
103 #ifndef OS
104 #define OS "Undefined"
105 #endif
106
107 static struct timeval now;
108
109 /* Timestamp node */
110 struct stamp {
111   union olsr_ip_addr addr;
112   /* Timestamp difference */
113   int diff;
114   uint32_t challenge;
115   uint8_t validated;
116   uint32_t valtime;                     /* Validity time */
117   uint32_t conftime;                    /* Reconfiguration time */
118   struct stamp *prev;
119   struct stamp *next;
120 };
121
122 /* Seconds to cache a valid timestamp entry */
123 #define TIMESTAMP_HOLD_TIME 30
124
125 /* Seconds to cache a not verified timestamp entry */
126 #define EXCHANGE_HOLD_TIME 5
127
128 static struct stamp timestamps[HASHSIZE];
129
130 char keyfile[FILENAME_MAX + 1];
131 char aes_key[16];
132
133 /* Event function to register with the sceduler */
134 #if 0
135 static void olsr_event(void);
136 #endif
137 static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
138 static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
139 static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
140 static int parse_challenge(struct interface *olsr_if, char *);
141 static int parse_cres(struct interface *olsr_if, char *);
142 static int parse_rres(char *);
143 static int check_auth(struct interface *olsr_if, char *, int *);
144 #if 0
145 static int ipc_send(char *, int);
146 #endif
147 static int add_signature(uint8_t *, int *);
148 static int validate_packet(struct interface *olsr_if, const char *, int *);
149 static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
150 static void timeout_timestamps(void *);
151 static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
152 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
153 static int read_key_from_file(const char *);
154
155 /**
156  *Do initialization here
157  *
158  *This function is called by the my_init
159  *function in uolsrd_plugin.c
160  */
161
162 int
163 secure_plugin_init(void)
164 {
165   int i;
166
167   /* Initialize the timestamp database */
168   for (i = 0; i < HASHSIZE; i++) {
169     timestamps[i].next = &timestamps[i];
170     timestamps[i].prev = &timestamps[i];
171   }
172   olsr_printf(1, "Timestamp database initialized\n");
173
174   if (!strlen(keyfile))
175     strscpy(keyfile, KEYFILE, sizeof(keyfile));
176
177   i = read_key_from_file(keyfile);
178
179   if (i < 0) {
180     olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
181     exit(1);
182   }
183   if (i == 0) {
184     olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
185     exit(1);
186   }
187
188   /* Register the packet transform function */
189   add_ptf(&add_signature);
190
191   olsr_preprocessor_add_function(&secure_preprocessor);
192
193   /* Register timeout - poll every 2 seconds */
194   olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &timeout_timestamps, NULL, 0);
195
196   return 1;
197 }
198
199 int
200 plugin_ipc_init(void)
201 {
202   return 1;
203 }
204
205 /*
206  * destructor - called at unload
207  */
208 void
209 secure_plugin_exit(void)
210 {
211   olsr_preprocessor_remove_function(&secure_preprocessor);
212 }
213
214 #if 0
215
216 /**
217  *Scheduled event
218  */
219 static void
220 olsr_event(void)
221 {
222
223 }
224 #endif
225
226 #if 0
227 static int
228 ipc_send(char *data __attribute__ ((unused)), int size __attribute__ ((unused)))
229 {
230   return 1;
231 }
232 #endif
233
234 static char *
235 secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
236 {
237   struct olsr *olsr = (struct olsr *)packet;
238   struct ipaddr_str buf;
239
240   /*
241    * Check for challenge/response messages
242    */
243   check_auth(olsr_if, packet, length);
244
245   /*
246    * Check signature
247    */
248
249   if (!validate_packet(olsr_if, packet, length)) {
250     olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
251     return NULL;
252   }
253
254   olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
255
256   /* Fix OLSR packet header */
257   olsr->olsr_packlen = htons(*length);
258   return packet;
259 }
260
261 /**
262  * Check a incoming OLSR packet for
263  * challenge/responses.
264  * They need not be verified as they
265  * are signed in the message.
266  *
267  */
268 static int
269 check_auth(struct interface *olsr_if, char *pck, int *size __attribute__ ((unused)))
270 {
271
272   olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
273
274   switch (pck[4]) {
275   case (TYPE_CHALLENGE):
276     parse_challenge(olsr_if, &pck[4]);
277     break;
278
279   case (TYPE_CRESPONSE):
280     parse_cres(olsr_if, &pck[4]);
281     break;
282
283   case (TYPE_RRESPONSE):
284     parse_rres(&pck[4]);
285     break;
286
287   default:
288     return 0;
289   }
290
291   return 1;
292 }
293
294 /**
295  * Packet transform function
296  * Build a SHA-1/MD5 hash of the original message
297  * + the signature message(-digest) + key
298  *
299  * Then add the signature message to the packet and
300  * increase the size
301  */
302 int
303 add_signature(uint8_t * pck, int *size)
304 {
305   struct s_olsrmsg *msg;
306 #ifdef DEBUG
307   unsigned int i;
308   int j;
309   const uint8_t *sigmsg;
310 #endif
311
312   olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
313   fflush(stdout);
314
315   msg = (struct s_olsrmsg *)ARM_NOWARN_ALIGN(&pck[*size]);
316   /* Update size */
317   ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
318
319   /* Fill packet header */
320   msg->olsr_msgtype = MESSAGE_TYPE;
321   msg->olsr_vtime = 0;
322   msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
323   memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
324   msg->ttl = 1;
325   msg->hopcnt = 0;
326   msg->seqno = htons(get_msg_seqno());
327
328   /* Fill subheader */
329   msg->sig.type = ONE_CHECKSUM;
330   msg->sig.algorithm = SCHEME;
331   memset(&msg->sig.reserved, 0, 2);
332
333   /* Add timestamp */
334   msg->sig.timestamp = htonl(now.tv_sec);
335 #ifndef WIN32
336   olsr_printf(3, "[ENC]timestamp: %lld\n", (long long)now.tv_sec);
337 #endif
338   /* Set the new size */
339   *size += sizeof(struct s_olsrmsg);
340
341   {
342     uint8_t checksum_cache[512 + KEYLENGTH];
343     /* Create packet + key cache */
344     /* First the OLSR packet + signature message - digest */
345     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
346     /* Then the key */
347     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
348
349     /* Create the hash */
350     CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
351   }
352
353 #ifdef DEBUG
354   olsr_printf(1, "Signature message:\n");
355
356   j = 0;
357   sigmsg = (uint8_t *) msg;
358
359   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
360     olsr_printf(1, "  %3i", sigmsg[i]);
361     j++;
362     if (j == 4) {
363       olsr_printf(1, "\n");
364       j = 0;
365     }
366   }
367 #endif
368
369   olsr_printf(3, "[ENC] Message signed\n");
370
371   return 1;
372 }
373
374 static int
375 validate_packet(struct interface *olsr_if, const char *pck, int *size)
376 {
377   int packetsize;
378   uint8_t sha1_hash[SIGNATURE_SIZE];
379   const struct s_olsrmsg *sig;
380   time_t rec_time;
381
382 #ifdef DEBUG
383   unsigned int i;
384   int j;
385   const uint8_t *sigmsg;
386 #endif
387
388   /* Find size - signature message */
389   packetsize = *size - sizeof(struct s_olsrmsg);
390
391   if (packetsize < 4)
392     return 0;
393
394   sig = (const struct s_olsrmsg *)CONST_ARM_NOWARN_ALIGN(&pck[packetsize]);
395
396   //olsr_printf(1, "Size: %d\n", packetsize);
397
398 #ifdef DEBUG
399   olsr_printf(1, "Input message:\n");
400
401   j = 0;
402   sigmsg = (const uint8_t *)sig;
403
404   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
405     olsr_printf(1, "  %3i", sigmsg[i]);
406     j++;
407     if (j == 4) {
408       olsr_printf(1, "\n");
409       j = 0;
410     }
411   }
412 #endif
413
414   /* Sanity check first */
415   if ((sig->olsr_msgtype != MESSAGE_TYPE) || (sig->olsr_vtime != 0)
416       || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
417     olsr_printf(1, "[ENC]Packet not sane!\n");
418     return 0;
419   }
420
421   /* Check scheme and type */
422   switch (sig->sig.type) {
423   case (ONE_CHECKSUM):
424     switch (sig->sig.algorithm) {
425     case (SCHEME):
426       goto one_checksum_SHA;    /* Ahhh... fix this */
427       break;
428
429     }
430     break;
431
432   default:
433     olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
434     return 0;
435   }
436   //olsr_printf(1, "Packet sane...\n");
437
438 one_checksum_SHA:
439
440   {
441     uint8_t checksum_cache[512 + KEYLENGTH];
442     /* Create packet + key cache */
443     /* First the OLSR packet + signature message - digest */
444     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
445     /* Then the key */
446     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
447
448     /* generate SHA-1 */
449     CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
450   }
451
452 #ifdef DEBUG
453   olsr_printf(1, "Recevied hash:\n");
454
455   sigmsg = (const uint8_t *)sig->sig.signature;
456
457   for (i = 0; i < SIGNATURE_SIZE; i++) {
458     olsr_printf(1, " %3i", sigmsg[i]);
459   }
460   olsr_printf(1, "\n");
461
462   olsr_printf(1, "Calculated hash:\n");
463
464   sigmsg = sha1_hash;
465
466   for (i = 0; i < SIGNATURE_SIZE; i++) {
467     olsr_printf(1, " %3i", sigmsg[i]);
468   }
469   olsr_printf(1, "\n");
470 #endif
471
472   if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
473     olsr_printf(1, "[ENC]Signature missmatch\n");
474     return 0;
475   }
476
477   /* Check timestamp */
478   rec_time = ntohl(sig->sig.timestamp);
479
480   if (!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
481     struct ipaddr_str buf;
482     olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
483                 olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
484     return 0;
485   }
486 #ifndef WIN32
487   olsr_printf(1, "[ENC]Received timestamp %lld diff: %lld\n", (long long)rec_time, (long long)now.tv_sec - (long long)rec_time);
488 #endif
489   /* Remove signature message */
490   *size = packetsize;
491   return 1;
492 }
493
494 int
495 check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
496 {
497   struct stamp *entry;
498   int diff;
499
500   entry = lookup_timestamp_entry(originator);
501
502   if (!entry) {
503     /* Initiate timestamp negotiation */
504
505     send_challenge(olsr_if, originator);
506
507     return 0;
508   }
509
510   if (!entry->validated) {
511     olsr_printf(1, "[ENC]Message from non-validated host!\n");
512     return 0;
513   }
514
515   diff = entry->diff - (now.tv_sec - tstamp);
516
517   olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
518
519   if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
520     olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
521     return 0;
522   }
523
524   /* ok - update diff */
525   entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
526
527   olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
528
529   /* update validtime */
530
531   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
532
533   return 1;
534 }
535
536 /**
537  * Create and send a timestamp
538  * challenge message to new_host
539  *
540  * The host is registered in the timestamps
541  * repository with valid=0
542  */
543
544 int
545 send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
546 {
547   struct challengemsg cmsg;
548   struct stamp *entry;
549   uint32_t challenge, hash;
550   struct ipaddr_str buf;
551
552   olsr_printf(1, "[ENC]Building CHALLENGE message\n");
553
554   /* Set the size including OLSR packet size */
555
556   challenge = rand() << 16;
557   challenge |= rand();
558
559   /* Fill challengemessage */
560   cmsg.olsr_msgtype = TYPE_CHALLENGE;
561   cmsg.olsr_vtime = 0;
562   cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
563   memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
564   cmsg.ttl = 1;
565   cmsg.hopcnt = 0;
566   cmsg.seqno = htons(get_msg_seqno());
567
568   /* Fill subheader */
569   memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
570   cmsg.challenge = htonl(challenge);
571
572   olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
573
574   {
575     uint8_t checksum_cache[512 + KEYLENGTH];
576     /* Create packet + key cache */
577     /* First the OLSR packet + signature message - digest */
578     memcpy(checksum_cache, &cmsg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
579     /* Then the key */
580     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
581
582     /* Create the hash */
583     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, cmsg.signature);
584   }
585   olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n", olsr_ip_to_string(&buf, new_host), challenge);
586
587   /* Add to buffer */
588   net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
589
590   /* Send the request */
591   net_output(olsr_if);
592
593   /* Create new entry */
594   entry = malloc(sizeof(struct stamp));
595
596   entry->diff = 0;
597   entry->validated = 0;
598   entry->challenge = challenge;
599
600   memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
601
602   /* update validtime - not validated */
603   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
604
605   hash = olsr_ip_hashing(new_host);
606
607   /* Queue */
608   timestamps[hash].next->prev = entry;
609   entry->next = timestamps[hash].next;
610   timestamps[hash].next = entry;
611   entry->prev = &timestamps[hash];
612
613   return 1;
614
615 }
616
617 int
618 parse_cres(struct interface *olsr_if, char *in_msg)
619 {
620   struct c_respmsg *msg;
621   uint8_t sha1_hash[SIGNATURE_SIZE];
622   struct stamp *entry;
623   struct ipaddr_str buf;
624
625   msg = (struct c_respmsg *)ARM_NOWARN_ALIGN(in_msg);
626
627   olsr_printf(1, "[ENC]Challenge-response message received\n");
628   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
629
630   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
631     olsr_printf(3, "[ENC]Not for us...\n");
632     return 0;
633   }
634
635   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
636
637   /* Check signature */
638
639   {
640     uint8_t checksum_cache[512 + KEYLENGTH];
641     /* Create packet + key cache */
642     /* First the OLSR packet + signature message - digest */
643     memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
644     /* Then the key */
645     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
646
647     /* Create the hash */
648     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
649   }
650
651   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
652     olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
653     return 0;
654   }
655
656   olsr_printf(3, "[ENC]Signature verified\n");
657
658   /* Now to check the digest from the emitted challenge */
659   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
660     olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
661                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
662     return 0;
663   }
664
665   /* Generate the digest */
666   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
667
668   {
669     uint8_t checksum_cache[512 + KEYLENGTH];
670     /* First the challenge received */
671     memcpy(checksum_cache, &entry->challenge, 4);
672     /* Then the local IP */
673     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
674
675     /* Create the hash */
676     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
677   }
678
679   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
680     olsr_printf(1, "[ENC]Error in challenge signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
681
682     return 0;
683   }
684
685   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
686
687   /* Update entry! */
688
689   entry->challenge = 0;
690   entry->validated = 1;
691   entry->diff = now.tv_sec - msg->timestamp;
692
693   /* update validtime - validated entry */
694   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
695
696   olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
697               entry->diff);
698
699   /* Send response-response */
700   send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge));
701
702   return 1;
703 }
704
705 int
706 parse_rres(char *in_msg)
707 {
708   struct r_respmsg *msg;
709   uint8_t sha1_hash[SIGNATURE_SIZE];
710   struct stamp *entry;
711   struct ipaddr_str buf;
712
713   msg = (struct r_respmsg *)ARM_NOWARN_ALIGN(in_msg);
714
715   olsr_printf(1, "[ENC]Response-response message received\n");
716   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
717
718   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
719     olsr_printf(1, "[ENC]Not for us...\n");
720     return 0;
721   }
722
723   /* Check signature */
724
725   {
726     uint8_t checksum_cache[512 + KEYLENGTH];
727     /* Create packet + key cache */
728     /* First the OLSR packet + signature message - digest */
729     memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
730     /* Then the key */
731     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
732
733     /* Create the hash */
734     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
735   }
736
737   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
738     olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
739     return 0;
740   }
741
742   olsr_printf(3, "[ENC]Signature verified\n");
743
744   /* Now to check the digest from the emitted challenge */
745   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
746     olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
747                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
748     return 0;
749   }
750
751   /* Generate the digest */
752   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
753
754   {
755     uint8_t checksum_cache[512 + KEYLENGTH];
756     /* First the challenge received */
757     memcpy(checksum_cache, &entry->challenge, 4);
758     /* Then the local IP */
759     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
760
761     /* Create the hash */
762     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
763   }
764
765   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
766     olsr_printf(1, "[ENC]Error in response signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
767
768     return 0;
769   }
770
771   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
772
773   /* Update entry! */
774
775   entry->challenge = 0;
776   entry->validated = 1;
777   entry->diff = now.tv_sec - msg->timestamp;
778
779   /* update validtime - validated entry */
780   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
781
782   olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
783               entry->diff);
784
785   return 1;
786 }
787
788 int
789 parse_challenge(struct interface *olsr_if, char *in_msg)
790 {
791   struct challengemsg *msg;
792   uint8_t sha1_hash[SIGNATURE_SIZE];
793   struct stamp *entry;
794   uint32_t hash;
795   struct ipaddr_str buf;
796
797   msg = (struct challengemsg *)ARM_NOWARN_ALIGN(in_msg);
798
799   olsr_printf(1, "[ENC]Challenge message received\n");
800   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
801
802   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
803     olsr_printf(1, "[ENC]Not for us...\n");
804     return 0;
805   }
806
807   /* Create entry if not registered */
808   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
809     entry = malloc(sizeof(struct stamp));
810     memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
811
812     hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
813
814     /* Queue */
815     timestamps[hash].next->prev = entry;
816     entry->next = timestamps[hash].next;
817     timestamps[hash].next = entry;
818     entry->prev = &timestamps[hash];
819   } else {
820     /* Check configuration timeout */
821     if (!TIMED_OUT(entry->conftime)) {
822       /* If registered - do not accept! */
823       olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
824       return 0;
825     } else {
826       olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
827     }
828   }
829
830   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
831
832   /* Check signature */
833
834   {
835     uint8_t checksum_cache[512 + KEYLENGTH];
836     /* Create packet + key cache */
837     /* First the OLSR packet + signature message - digest */
838     memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
839     /* Then the key */
840     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
841
842     /* Create the hash */
843     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
844   }
845   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
846     olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
847     return 0;
848   }
849
850   olsr_printf(3, "[ENC]Signature verified\n");
851
852   entry->diff = 0;
853   entry->validated = 0;
854
855   /* update validtime - not validated */
856   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
857
858   /* Build and send response */
859
860   send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry);
861
862   return 1;
863 }
864
865 /**
866  * Build and transmit a challenge response
867  * message.
868  *
869  */
870 int
871 send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
872 {
873   struct c_respmsg crmsg;
874   uint32_t challenge;
875   struct ipaddr_str buf;
876
877   olsr_printf(1, "[ENC]Building CRESPONSE message\n");
878
879   challenge = rand() << 16;
880   challenge |= rand();
881
882   entry->challenge = challenge;
883
884   olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
885
886   /* Fill challengemessage */
887   crmsg.olsr_msgtype = TYPE_CRESPONSE;
888   crmsg.olsr_vtime = 0;
889   crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
890   memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
891   crmsg.ttl = 1;
892   crmsg.hopcnt = 0;
893   crmsg.seqno = htons(get_msg_seqno());
894
895   /* set timestamp */
896   crmsg.timestamp = now.tv_sec;
897 #ifndef WIN32
898   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)crmsg.timestamp);
899 #endif
900
901   /* Fill subheader */
902   memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
903   crmsg.challenge = htonl(challenge);
904
905   /* Create digest of received challenge + IP */
906
907   {
908     uint8_t checksum_cache[512 + KEYLENGTH];
909     /* Create packet + key cache */
910     /* First the challenge received */
911     memcpy(checksum_cache, &chal_in, 4);
912     /* Then the local IP */
913     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
914
915     /* Create the hash */
916     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, crmsg.res_sig);
917   }
918
919   /* Now create the digest of the message and the key */
920
921   {
922     uint8_t checksum_cache[512 + KEYLENGTH];
923     /* Create packet + key cache */
924     /* First the OLSR packet + signature message - digest */
925     memcpy(checksum_cache, &crmsg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
926     /* Then the key */
927     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
928
929     /* Create the hash */
930     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, crmsg.signature);
931   }
932
933   olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
934
935   /* Add to buffer */
936   net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
937   /* Send the request */
938   net_output(olsr_if);
939
940   return 1;
941 }
942
943 /**
944  * Build and transmit a response response
945  * message.
946  *
947  */
948 static int
949 send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
950 {
951   struct r_respmsg rrmsg;
952   struct ipaddr_str buf;
953
954   olsr_printf(1, "[ENC]Building RRESPONSE message\n");
955
956   /* Fill challengemessage */
957   rrmsg.olsr_msgtype = TYPE_RRESPONSE;
958   rrmsg.olsr_vtime = 0;
959   rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
960   memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
961   rrmsg.ttl = 1;
962   rrmsg.hopcnt = 0;
963   rrmsg.seqno = htons(get_msg_seqno());
964
965   /* set timestamp */
966   rrmsg.timestamp = now.tv_sec;
967
968 #ifndef WIN32
969   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)rrmsg.timestamp);
970 #endif
971   /* Fill subheader */
972   memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
973
974   /* Create digest of received challenge + IP */
975
976   {
977     uint8_t checksum_cache[512 + KEYLENGTH];
978     /* Create packet + key cache */
979     /* First the challenge received */
980     memcpy(checksum_cache, &chal_in, 4);
981     /* Then the local IP */
982     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
983
984     /* Create the hash */
985     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, rrmsg.res_sig);
986   }
987
988   /* Now create the digest of the message and the key */
989
990   {
991     uint8_t checksum_cache[512 + KEYLENGTH];
992     /* Create packet + key cache */
993     /* First the OLSR packet + signature message - digest */
994     memcpy(checksum_cache, &rrmsg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
995     /* Then the key */
996     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
997
998     /* Create the hash */
999     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, rrmsg.signature);
1000   }
1001
1002   olsr_printf(3, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1003
1004   /* add to buffer */
1005   net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
1006
1007   /* Send the request */
1008   net_output(olsr_if);
1009
1010   return 1;
1011 }
1012
1013 static struct stamp *
1014 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1015 {
1016   uint32_t hash;
1017   struct stamp *entry;
1018   struct ipaddr_str buf;
1019
1020   hash = olsr_ip_hashing(adr);
1021
1022   for (entry = timestamps[hash].next; entry != &timestamps[hash]; entry = entry->next) {
1023     if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1024       olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1025       return entry;
1026     }
1027   }
1028
1029   olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1030
1031   return NULL;
1032 }
1033
1034 /**
1035  *Find timed out entries and delete them
1036  *
1037  *@return nada
1038  */
1039 void
1040 timeout_timestamps(void *foo __attribute__ ((unused)))
1041 {
1042   struct stamp *tmp_list;
1043   struct stamp *entry_to_delete;
1044   int idx;
1045
1046   /* Update our local timestamp */
1047   gettimeofday(&now, NULL);
1048
1049   for (idx = 0; idx < HASHSIZE; idx++) {
1050     tmp_list = timestamps[idx].next;
1051     /*Traverse MID list */
1052     while (tmp_list != &timestamps[idx]) {
1053       /*Check if the entry is timed out */
1054       if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1055         struct ipaddr_str buf;
1056         entry_to_delete = tmp_list;
1057         tmp_list = tmp_list->next;
1058
1059         olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n", olsr_ip_to_string(&buf, &entry_to_delete->addr));
1060
1061         /*Delete it */
1062         entry_to_delete->next->prev = entry_to_delete->prev;
1063         entry_to_delete->prev->next = entry_to_delete->next;
1064
1065         free(entry_to_delete);
1066       } else
1067         tmp_list = tmp_list->next;
1068     }
1069   }
1070
1071   return;
1072 }
1073
1074 static int
1075 read_key_from_file(const char *file)
1076 {
1077   FILE *kf;
1078   size_t keylen;
1079
1080   keylen = 16;
1081   kf = fopen(file, "r");
1082
1083   olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
1084
1085   if (kf == NULL) {
1086     olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1087     return -1;
1088   }
1089
1090   if (fread(aes_key, 1, keylen, kf) != keylen) {
1091     olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1092     fclose(kf);
1093     return 0;
1094   }
1095
1096   fclose(kf);
1097   return 1;
1098 }
1099
1100 /*
1101  * Local Variables:
1102  * c-basic-offset: 2
1103  * indent-tabs-mode: nil
1104  * End:
1105  */