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