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