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