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