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