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