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