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