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