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