bed559a58ba37c2e380e873f64864ffc2d763cc1
[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 #include "olsr_logging.h"
67
68 #ifdef USE_OPENSSL
69
70 /* OpenSSL stuff */
71 #include <openssl/sha.h>
72
73 #define CHECKSUM SHA1
74 #define SCHEME   SHA1_INCLUDING_KEY
75
76 #else
77
78 /* Homebrewn checksuming */
79 #include "md5.h"
80
81 static void
82 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
83 {
84   MD5_CTX context;
85
86   MD5Init(&context);
87   MD5Update(&context, data, data_len);
88   MD5Final(hashbuf, &context);
89 }
90
91 #define CHECKSUM MD5_checksum
92 #define SCHEME   MD5_INCLUDING_KEY
93
94 #endif
95
96 #ifdef OS
97 #undef OS
98 #endif
99
100 #ifdef WIN32
101 #undef EWOULDBLOCK
102 #define EWOULDBLOCK WSAEWOULDBLOCK
103 #define OS "Windows"
104 #endif
105 #ifdef linux
106 #define OS "GNU/Linux"
107 #endif
108 #ifdef __FreeBSD__
109 #define OS "FreeBSD"
110 #endif
111
112 #ifndef OS
113 #define OS "Undefined"
114 #endif
115
116 static struct timeval now;
117
118 /* Timestamp node */
119 struct stamp {
120   union olsr_ip_addr addr;
121   /* Timestamp difference */
122   int diff;
123   uint32_t challenge;
124   uint8_t validated;
125   uint32_t valtime;                    /* Validity time */
126   uint32_t conftime;                   /* Reconfiguration time */
127   struct stamp *prev;
128   struct stamp *next;
129 };
130
131 /* Seconds to cache a valid timestamp entry */
132 #define TIMESTAMP_HOLD_TIME 30
133
134 /* Seconds to cache a not verified timestamp entry */
135 #define EXCHANGE_HOLD_TIME 5
136
137 static struct stamp timestamps[HASHSIZE];
138
139
140 char keyfile[FILENAME_MAX + 1];
141 char aes_key[16];
142
143 /* Event function to register with the sceduler */
144 #if 0
145 static void olsr_event(void);
146 #endif
147 static int send_challenge(struct interface *olsr_if_config, const union olsr_ip_addr *);
148 static int send_cres(struct interface *olsr_if_config, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
149 static int send_rres(struct interface *olsr_if_config, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
150 static int parse_challenge(struct interface *olsr_if_config, char *);
151 static int parse_cres(struct interface *olsr_if_config, char *);
152 static int parse_rres(char *);
153 static int check_auth(struct interface *olsr_if_config, char *, int *);
154 #if 0
155 static int ipc_send(char *, int);
156 #endif
157 static int add_signature(uint8_t *, int *);
158 static int validate_packet(struct interface *olsr_if_config, const char *, int *);
159 static char *secure_preprocessor(char *packet, struct interface *olsr_if_config, union olsr_ip_addr *from_addr, int *length);
160 static void timeout_timestamps(void *);
161 static int check_timestamp(struct interface *olsr_if_config, const union olsr_ip_addr *, time_t);
162 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
163 static int read_key_from_file(const char *);
164
165 static struct olsr_cookie_info *timeout_timestamps_timer_cookie;
166
167 /**
168  *Do initialization here
169  *
170  *This function is called by the my_init
171  *function in uolsrd_plugin.c
172  */
173 int
174 secure_plugin_init(void)
175 {
176   int i;
177
178
179   /* Initialize the timestamp database */
180   for (i = 0; i < HASHSIZE; i++) {
181     timestamps[i].next = &timestamps[i];
182     timestamps[i].prev = &timestamps[i];
183   }
184   OLSR_INFO(LOG_PLUGINS, "Timestamp database initialized\n");
185
186   if (!strlen(keyfile))
187     strscpy(keyfile, KEYFILE, sizeof(keyfile));
188
189   i = read_key_from_file(keyfile);
190
191   if (i < 0) {
192     OLSR_ERROR(LOG_PLUGINS, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
193     olsr_exit(1);
194   }
195   if (i == 0) {
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, &timeout_timestamps, NULL, timeout_timestamps_timer_cookie);
210
211   return 1;
212 }
213
214 int
215 plugin_ipc_init(void)
216 {
217   return 1;
218 }
219
220 /*
221  * destructor - called at unload
222  */
223 void
224 secure_plugin_exit(void)
225 {
226   olsr_preprocessor_remove_function(&secure_preprocessor);
227 }
228
229
230 #if 0
231
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
252                     __attribute__ ((unused)), int *length)
253 {
254   struct olsr *olsr = (struct olsr *)packet;
255 #if !defined REMOVE_LOG_DEBUG
256   struct ipaddr_str buf;
257 #endif
258   /*
259    * Check for challenge/response messages
260    */
261   check_auth(olsr_if_config, packet, length);
262
263   /*
264    * Check signature
265    */
266
267   if (!validate_packet(olsr_if_config, packet, length)) {
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   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 #endif
330
331   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Adding signature for packet size %d\n", *size);
332
333   msg = (struct s_olsrmsg *)(ARM_NOWARN_ALIGN)&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->router_id, 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_DEBUG(LOG_PLUGINS, "[ENC]timestamp: %ld\n", (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 #if 0
371   {
372     unsigned int i;
373     int j;
374     const uint8_t *sigmsg;
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       OLSR_PRINTF(1, "  %3i", sigmsg[i]);
382       j++;
383       if (j == 4) {
384         OLSR_PRINTF(1, "\n");
385         j = 0;
386       }
387     }
388   }
389 #endif
390
391   OLSR_DEBUG(LOG_PLUGINS, "[ENC] Message signed\n");
392
393   return 1;
394 }
395
396
397
398 static int
399 validate_packet(struct interface *olsr_if_config, const char *pck, int *size)
400 {
401   int packetsize;
402   uint8_t sha1_hash[SIGNATURE_SIZE];
403   const struct s_olsrmsg *sig;
404   time_t rec_time;
405
406   /* Find size - signature message */
407   packetsize = *size - sizeof(struct s_olsrmsg);
408
409   if (packetsize < 4)
410     return 0;
411
412   sig = (const struct s_olsrmsg *)(const ARM_NOWARN_ALIGN)&pck[packetsize];
413
414   //OLSR_PRINTF(1, "Size: %d\n", packetsize);
415
416 #if 0
417   {
418     unsigned int i;
419     int j;
420     const uint8_t *sigmsg;
421     OLSR_PRINTF(1, "Input message:\n");
422
423     j = 0;
424     sigmsg = (const uint8_t *)sig;
425
426     for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
427       OLSR_PRINTF(1, "  %3i", sigmsg[i]);
428       j++;
429       if (j == 4) {
430         OLSR_PRINTF(1, "\n");
431         j = 0;
432       }
433     }
434   }
435 #endif
436
437   /* Sanity check first */
438   if ((sig->olsr_msgtype != MESSAGE_TYPE) ||
439       (sig->olsr_vtime != 0) || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
440     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Packet not sane!\n");
441     return 0;
442   }
443
444   /* Check scheme and type */
445   switch (sig->sig.type) {
446   case (ONE_CHECKSUM):
447     switch (sig->sig.algorithm) {
448     case (SCHEME):
449       goto one_checksum_SHA;    /* Ahhh... fix this */
450       break;
451
452     }
453     break;
454
455   default:
456     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
457     return 0;
458   }
459   //OLSR_PRINTF(1, "Packet sane...\n");
460
461 one_checksum_SHA:
462
463   {
464     uint8_t checksum_cache[512 + KEYLENGTH];
465     /* Create packet + key cache */
466     /* First the OLSR packet + signature message - digest */
467     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
468     /* Then the key */
469     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
470
471     /* generate SHA-1 */
472     CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
473   }
474
475 #if 0
476   OLSR_PRINTF(1, "Recevied hash:\n");
477
478   sigmsg = (const uint8_t *)sig->sig.signature;
479
480   for (i = 0; i < SIGNATURE_SIZE; i++) {
481     OLSR_PRINTF(1, " %3i", sigmsg[i]);
482   }
483   OLSR_PRINTF(1, "\n");
484
485   OLSR_PRINTF(1, "Calculated hash:\n");
486
487   sigmsg = sha1_hash;
488
489   for (i = 0; i < SIGNATURE_SIZE; i++) {
490     OLSR_PRINTF(1, " %3i", sigmsg[i]);
491   }
492   OLSR_PRINTF(1, "\n");
493 #endif
494
495   if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
496     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch\n");
497     return 0;
498   }
499
500   /* Check timestamp */
501   rec_time = ntohl(sig->sig.timestamp);
502
503   if (!check_timestamp(olsr_if_config, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
504 #if !defined REMOVE_LOG_DEBUG
505     struct ipaddr_str buf;
506 #endif
507     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp missmatch in packet from %s!\n",
508                olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
509     return 0;
510   }
511
512   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Received timestamp %ld diff: %ld\n", (long)rec_time,
513              (long)now.tv_sec - (long)rec_time);
514
515   /* Remove signature message */
516   *size = packetsize;
517   return 1;
518 }
519
520
521 int
522 check_timestamp(struct interface *olsr_if_config, const union olsr_ip_addr *originator, time_t tstamp)
523 {
524   struct stamp *entry;
525   int diff;
526
527   entry = lookup_timestamp_entry(originator);
528
529   if (!entry) {
530     /* Initiate timestamp negotiation */
531
532     send_challenge(olsr_if_config, originator);
533
534     return 0;
535   }
536
537   if (!entry->validated) {
538     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Message from non-validated host!\n");
539     return 0;
540   }
541
542   diff = entry->diff - (now.tv_sec - tstamp);
543
544   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp slack: %d\n", diff);
545
546   if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
547     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp scew detected!!\n");
548     return 0;
549   }
550
551   /* ok - update diff */
552   entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
553
554   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Diff set to : %d\n", entry->diff);
555
556   /* update validtime */
557
558   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
559
560   return 1;
561 }
562
563
564 /**
565  * Create and send a timestamp
566  * challenge message to new_host
567  *
568  * The host is registered in the timestamps
569  * repository with valid=0
570  */
571
572 int
573 send_challenge(struct interface *olsr_if_config, const union olsr_ip_addr *new_host)
574 {
575   struct challengemsg cmsg;
576   struct stamp *entry;
577   uint32_t challenge, hash;
578 #if !defined REMOVE_LOG_DEBUG
579   struct ipaddr_str buf;
580 #endif
581
582   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building CHALLENGE message\n");
583
584   /* Set the size including OLSR packet size */
585
586
587   challenge = rand() << 16;
588   challenge |= rand();
589
590   /* Fill challengemessage */
591   cmsg.olsr_msgtype = TYPE_CHALLENGE;
592   cmsg.olsr_vtime = 0;
593   cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
594   memcpy(&cmsg.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
595   cmsg.ttl = 1;
596   cmsg.hopcnt = 0;
597   cmsg.seqno = htons(get_msg_seqno());
598
599   /* Fill subheader */
600   memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
601   cmsg.challenge = htonl(challenge);
602
603   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
604
605   {
606     uint8_t checksum_cache[512 + KEYLENGTH];
607     /* Create packet + key cache */
608     /* First the OLSR packet + signature message - digest */
609     memcpy(checksum_cache, &cmsg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
610     /* Then the key */
611     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
612
613     /* Create the hash */
614     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, cmsg.signature);
615   }
616   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending timestamp request to %s challenge 0x%x\n", olsr_ip_to_string(&buf, new_host), challenge);
617
618   /* Add to buffer */
619   net_outbuffer_push(olsr_if_config, &cmsg, sizeof(struct challengemsg));
620
621   /* Send the request */
622   net_output(olsr_if_config);
623
624   /* Create new entry */
625   entry = malloc(sizeof(struct stamp));
626
627   entry->diff = 0;
628   entry->validated = 0;
629   entry->challenge = challenge;
630
631   memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
632
633   /* update validtime - not validated */
634   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
635
636   hash = olsr_ip_hashing(new_host);
637
638   /* Queue */
639   timestamps[hash].next->prev = entry;
640   entry->next = timestamps[hash].next;
641   timestamps[hash].next = entry;
642   entry->prev = &timestamps[hash];
643
644
645   return 1;
646
647 }
648
649 int
650 parse_cres(struct interface *olsr_if_config, char *in_msg)
651 {
652   struct c_respmsg *msg;
653   uint8_t sha1_hash[SIGNATURE_SIZE];
654   struct stamp *entry;
655 #if !defined REMOVE_LOG_DEBUG
656   struct ipaddr_str buf;
657 #endif
658
659   msg = (struct c_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
660
661   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response message received\n");
662   OLSR_DEBUG(LOG_PLUGINS, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
663
664   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
665     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
666     return 0;
667   }
668
669   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));     /* ntohl() returns a unsignedlong onwin32 */
670
671   /* Check signature */
672
673   {
674     uint8_t checksum_cache[512 + KEYLENGTH];
675     /* Create packet + key cache */
676     /* First the OLSR packet + signature message - digest */
677     memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
678     /* Then the key */
679     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
680
681     /* Create the hash */
682     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
683   }
684
685   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
686     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in challenge-response!\n");
687     return 0;
688   }
689
690   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
691
692
693   /* Now to check the digest from the emitted challenge */
694   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
695     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Received challenge-response from non-registered node %s!\n",
696                olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
697     return 0;
698   }
699
700   /* Generate the digest */
701   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
702
703   {
704     uint8_t checksum_cache[512 + KEYLENGTH];
705     /* First the challenge received */
706     memcpy(checksum_cache, &entry->challenge, 4);
707     /* Then the local IP */
708     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
709
710     /* Create the hash */
711     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
712   }
713
714   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
715     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Error in challenge signature from %s!\n",
716                olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
717
718     return 0;
719   }
720
721   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response signature ok\n");
722
723   /* Update entry! */
724
725
726   entry->challenge = 0;
727   entry->validated = 1;
728   entry->diff = now.tv_sec - msg->timestamp;
729
730   /* update validtime - validated entry */
731   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
732
733   OLSR_DEBUG(LOG_PLUGINS, "[ENC]%s registered with diff %d!\n",
734              olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator), entry->diff);
735
736   /* Send response-response */
737   send_rres(olsr_if_config, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge));
738
739   return 1;
740 }
741
742
743 int
744 parse_rres(char *in_msg)
745 {
746   struct r_respmsg *msg;
747   uint8_t sha1_hash[SIGNATURE_SIZE];
748   struct stamp *entry;
749 #if !defined REMOVE_LOG_DEBUG
750   struct ipaddr_str buf;
751 #endif
752
753   msg = (struct r_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
754
755   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Response-response message received\n");
756   OLSR_DEBUG(LOG_PLUGINS, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
757
758   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
759     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
760     return 0;
761   }
762
763   /* Check signature */
764
765   {
766     uint8_t checksum_cache[512 + KEYLENGTH];
767     /* Create packet + key cache */
768     /* First the OLSR packet + signature message - digest */
769     memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
770     /* Then the key */
771     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
772
773     /* Create the hash */
774     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
775   }
776
777   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
778     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in response-response!\n");
779     return 0;
780   }
781
782   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
783
784
785   /* Now to check the digest from the emitted challenge */
786   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
787     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Received response-response from non-registered node %s!\n",
788                olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
789     return 0;
790   }
791
792   /* Generate the digest */
793   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
794
795   {
796     uint8_t checksum_cache[512 + KEYLENGTH];
797     /* First the challenge received */
798     memcpy(checksum_cache, &entry->challenge, 4);
799     /* Then the local IP */
800     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
801
802     /* Create the hash */
803     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
804   }
805
806   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
807     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Error in response signature from %s!\n",
808                olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
809
810     return 0;
811   }
812
813   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response signature ok\n");
814
815   /* Update entry! */
816
817
818   entry->challenge = 0;
819   entry->validated = 1;
820   entry->diff = now.tv_sec - msg->timestamp;
821
822   /* update validtime - validated entry */
823   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
824
825   OLSR_DEBUG(LOG_PLUGINS, "[ENC]%s registered with diff %d!\n",
826              olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator), entry->diff);
827
828   return 1;
829 }
830
831
832 int
833 parse_challenge(struct interface *olsr_if_config, char *in_msg)
834 {
835   struct challengemsg *msg;
836   uint8_t sha1_hash[SIGNATURE_SIZE];
837   struct stamp *entry;
838   uint32_t hash;
839 #if !defined REMOVE_LOG_DEBUG
840   struct ipaddr_str buf;
841 #endif
842
843   msg = (struct challengemsg *)(ARM_NOWARN_ALIGN)in_msg;
844
845   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge message received\n");
846   OLSR_DEBUG(LOG_PLUGINS, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
847
848   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
849     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
850     return 0;
851   }
852
853   /* Create entry if not registered */
854   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
855     entry = malloc(sizeof(struct stamp));
856     memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
857
858     hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
859
860     /* Queue */
861     timestamps[hash].next->prev = entry;
862     entry->next = timestamps[hash].next;
863     timestamps[hash].next = entry;
864     entry->prev = &timestamps[hash];
865   } else {
866     /* Check configuration timeout */
867     if (!TIMED_OUT(entry->conftime)) {
868       /* If registered - do not accept! */
869       OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge from registered node...dropping!\n");
870       return 0;
871     } else {
872       OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge from registered node...accepted!\n");
873     }
874   }
875
876   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));     /* ntohl() returns a unsignedlong onwin32 */
877
878   /* Check signature */
879
880   {
881     uint8_t checksum_cache[512 + KEYLENGTH];
882     /* Create packet + key cache */
883     /* First the OLSR packet + signature message - digest */
884     memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
885     /* Then the key */
886     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
887
888     /* Create the hash */
889     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
890   }
891   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
892     OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in challenge!\n");
893     return 0;
894   }
895
896   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
897
898
899   entry->diff = 0;
900   entry->validated = 0;
901
902   /* update validtime - not validated */
903   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
904
905   /* Build and send response */
906
907   send_cres(olsr_if_config, (union olsr_ip_addr *)&msg->originator,
908             (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry);
909
910   return 1;
911 }
912
913
914
915
916
917 /**
918  * Build and transmit a challenge response
919  * message.
920  *
921  */
922 int
923 send_cres(struct interface *olsr_if_config, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
924 {
925   struct c_respmsg crmsg;
926   uint32_t challenge;
927 #if !defined REMOVE_LOG_DEBUG
928   struct ipaddr_str buf;
929 #endif
930
931   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building CRESPONSE message\n");
932
933   challenge = rand() << 16;
934   challenge |= rand();
935
936   entry->challenge = challenge;
937
938   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response: 0x%x\n", challenge);
939
940   /* Fill challengemessage */
941   crmsg.olsr_msgtype = TYPE_CRESPONSE;
942   crmsg.olsr_vtime = 0;
943   crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
944   memcpy(&crmsg.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
945   crmsg.ttl = 1;
946   crmsg.hopcnt = 0;
947   crmsg.seqno = htons(get_msg_seqno());
948
949   /* set timestamp */
950   crmsg.timestamp = now.tv_sec;
951   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp %ld\n", (long)crmsg.timestamp);
952
953   /* Fill subheader */
954   memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
955   crmsg.challenge = htonl(challenge);
956
957   /* Create digest of received challenge + IP */
958
959   {
960     uint8_t checksum_cache[512 + KEYLENGTH];
961     /* Create packet + key cache */
962     /* First the challenge received */
963     memcpy(checksum_cache, &chal_in, 4);
964     /* Then the local IP */
965     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
966
967     /* Create the hash */
968     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, crmsg.res_sig);
969   }
970
971   /* Now create the digest of the message and the key */
972
973   {
974     uint8_t checksum_cache[512 + KEYLENGTH];
975     /* Create packet + key cache */
976     /* First the OLSR packet + signature message - digest */
977     memcpy(checksum_cache, &crmsg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
978     /* Then the key */
979     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
980
981     /* Create the hash */
982     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, crmsg.signature);
983   }
984
985   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
986
987   /* Add to buffer */
988   net_outbuffer_push(olsr_if_config, &crmsg, sizeof(struct c_respmsg));
989   /* Send the request */
990   net_output(olsr_if_config);
991
992   return 1;
993 }
994
995
996
997
998
999
1000 /**
1001  * Build and transmit a response response
1002  * message.
1003  *
1004  */
1005 static int
1006 send_rres(struct interface *olsr_if_config, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
1007 {
1008   struct r_respmsg rrmsg;
1009 #if !defined REMOVE_LOG_DEBUG
1010   struct ipaddr_str buf;
1011 #endif
1012
1013   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building RRESPONSE message\n");
1014
1015
1016   /* Fill challengemessage */
1017   rrmsg.olsr_msgtype = TYPE_RRESPONSE;
1018   rrmsg.olsr_vtime = 0;
1019   rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
1020   memcpy(&rrmsg.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
1021   rrmsg.ttl = 1;
1022   rrmsg.hopcnt = 0;
1023   rrmsg.seqno = htons(get_msg_seqno());
1024
1025   /* set timestamp */
1026   rrmsg.timestamp = now.tv_sec;
1027   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp %ld\n", (long)rrmsg.timestamp);
1028
1029   /* Fill subheader */
1030   memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
1031
1032   /* Create digest of received challenge + IP */
1033
1034   {
1035     uint8_t checksum_cache[512 + KEYLENGTH];
1036     /* Create packet + key cache */
1037     /* First the challenge received */
1038     memcpy(checksum_cache, &chal_in, 4);
1039     /* Then the local IP */
1040     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
1041
1042     /* Create the hash */
1043     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, rrmsg.res_sig);
1044   }
1045
1046   /* Now create the digest of the message and the key */
1047
1048   {
1049     uint8_t checksum_cache[512 + KEYLENGTH];
1050     /* Create packet + key cache */
1051     /* First the OLSR packet + signature message - digest */
1052     memcpy(checksum_cache, &rrmsg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
1053     /* Then the key */
1054     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
1055
1056     /* Create the hash */
1057     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, rrmsg.signature);
1058   }
1059
1060   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1061
1062   /* add to buffer */
1063   net_outbuffer_push(olsr_if_config, &rrmsg, sizeof(struct r_respmsg));
1064
1065   /* Send the request */
1066   net_output(olsr_if_config);
1067
1068   return 1;
1069 }
1070
1071
1072
1073 static struct stamp *
1074 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1075 {
1076   uint32_t hash;
1077   struct stamp *entry;
1078 #if !defined REMOVE_LOG_DEBUG
1079   struct ipaddr_str buf;
1080 #endif
1081
1082   hash = olsr_ip_hashing(adr);
1083
1084   for (entry = timestamps[hash].next; entry != &timestamps[hash]; entry = entry->next) {
1085     if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1086       OLSR_DEBUG(LOG_PLUGINS, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1087       return entry;
1088     }
1089   }
1090
1091   OLSR_DEBUG(LOG_PLUGINS, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1092
1093   return NULL;
1094 }
1095
1096
1097
1098 /**
1099  *Find timed out entries and delete them
1100  *
1101  *@return nada
1102  */
1103 void
1104 timeout_timestamps(void *foo __attribute__ ((unused)))
1105 {
1106   struct stamp *tmp_list;
1107   struct stamp *entry_to_delete;
1108   int idx;
1109
1110   /* Update our local timestamp */
1111   gettimeofday(&now, NULL);
1112
1113   for (idx = 0; idx < HASHSIZE; idx++) {
1114     tmp_list = timestamps[idx].next;
1115     /*Traverse MID list */
1116     while (tmp_list != &timestamps[idx]) {
1117       /*Check if the entry is timed out */
1118       if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1119 #if !defined REMOVE_LOG_DEBUG
1120         struct ipaddr_str buf;
1121 #endif
1122         entry_to_delete = tmp_list;
1123         tmp_list = tmp_list->next;
1124
1125         OLSR_DEBUG(LOG_PLUGINS, "[ENC]timestamp info for %s timed out.. deleting it\n",
1126                    olsr_ip_to_string(&buf, &entry_to_delete->addr));
1127
1128         /*Delete it */
1129         entry_to_delete->next->prev = entry_to_delete->prev;
1130         entry_to_delete->prev->next = entry_to_delete->next;
1131
1132         free(entry_to_delete);
1133       } else
1134         tmp_list = tmp_list->next;
1135     }
1136   }
1137
1138   return;
1139 }
1140
1141
1142
1143 static int
1144 read_key_from_file(const char *file)
1145 {
1146   FILE *kf;
1147   size_t keylen;
1148
1149   keylen = 16;
1150   kf = fopen(file, "r");
1151
1152   OLSR_DEBUG(LOG_PLUGINS, "[ENC]Reading key from file \"%s\"\n", file);
1153
1154   if (kf == NULL) {
1155     OLSR_WARN(LOG_PLUGINS, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1156     return -1;
1157   }
1158
1159   if (fread(aes_key, 1, keylen, kf) != keylen) {
1160     OLSR_WARN(LOG_PLUGINS, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1161     fclose(kf);
1162     return 0;
1163   }
1164
1165
1166   fclose(kf);
1167   return 1;
1168 }
1169
1170
1171 /*
1172  * Local Variables:
1173  * c-basic-offset: 2
1174  * indent-tabs-mode: nil
1175  * End:
1176  */