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