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