3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
44 * Dynamic linked library for the olsr.org olsr daemon
47 #include "olsrd_secure.h"
53 #include <linux/in_route.h>
63 #include "scheduler.h"
65 #include "common/string.h"
66 #include "olsr_logging.h"
71 #include <openssl/sha.h>
74 #define SCHEME SHA1_INCLUDING_KEY
78 /* Homebrewn checksuming */
82 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
87 MD5Update(&context, data, data_len);
88 MD5Final(hashbuf, &context);
91 #define CHECKSUM MD5_checksum
92 #define SCHEME MD5_INCLUDING_KEY
102 #define EWOULDBLOCK WSAEWOULDBLOCK
106 #define OS "GNU/Linux"
113 #define OS "Undefined"
116 static struct timeval now;
120 union olsr_ip_addr addr;
121 /* Timestamp difference */
125 uint32_t valtime; /* Validity time */
126 uint32_t conftime; /* Reconfiguration time */
131 /* Seconds to cache a valid timestamp entry */
132 #define TIMESTAMP_HOLD_TIME 30
134 /* Seconds to cache a not verified timestamp entry */
135 #define EXCHANGE_HOLD_TIME 5
137 static struct stamp timestamps[HASHSIZE];
140 char keyfile[FILENAME_MAX + 1];
143 /* Event function to register with the sceduler */
145 static void olsr_event(void);
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 *);
155 static int ipc_send(char *, int);
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 *);
165 static struct olsr_cookie_info *timeout_timestamps_timer_cookie;
168 *Do initialization here
170 *This function is called by the my_init
171 *function in uolsrd_plugin.c
174 secure_plugin_init(void)
179 /* Initialize the timestamp database */
180 for (i = 0; i < HASHSIZE; i++) {
181 timestamps[i].next = ×tamps[i];
182 timestamps[i].prev = ×tamps[i];
184 OLSR_INFO(LOG_PLUGINS, "Timestamp database initialized\n");
186 if (!strlen(keyfile))
187 strscpy(keyfile, KEYFILE, sizeof(keyfile));
189 i = read_key_from_file(keyfile);
192 OLSR_ERROR(LOG_PLUGINS, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
196 OLSR_ERROR(LOG_PLUGINS, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
200 /* Register the packet transform function */
201 add_ptf(&add_signature);
203 olsr_preprocessor_add_function(&secure_preprocessor);
205 /* create the cookie */
206 timeout_timestamps_timer_cookie = olsr_alloc_cookie("Secure: Timeout Timestamps", OLSR_COOKIE_TYPE_TIMER);
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);
215 plugin_ipc_init(void)
221 * destructor - called at unload
224 secure_plugin_exit(void)
226 olsr_preprocessor_remove_function(&secure_preprocessor);
244 ipc_send(char *data __attribute__ ((unused)), int size __attribute__ ((unused)))
251 secure_preprocessor(char *packet, struct interface *olsr_if_config, union olsr_ip_addr *from_addr
252 __attribute__ ((unused)), int *length)
254 struct olsr *olsr = (struct olsr *)packet;
255 #if !defined REMOVE_LOG_DEBUG
256 struct ipaddr_str buf;
259 * Check for challenge/response messages
261 check_auth(olsr_if_config, packet, length);
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));
272 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
274 /* Fix OLSR packet header */
275 olsr->olsr_packlen = htons(*length);
282 * Check a incoming OLSR packet for
283 * challenge/responses.
284 * They need not be verified as they
285 * are signed in the message.
289 check_auth(struct interface *olsr_if_config, char *pck, int *size __attribute__ ((unused)))
292 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Checking packet for challenge response message...\n");
295 case (TYPE_CHALLENGE):
296 parse_challenge(olsr_if_config, &pck[4]);
299 case (TYPE_CRESPONSE):
300 parse_cres(olsr_if_config, &pck[4]);
303 case (TYPE_RRESPONSE):
317 * Packet transform function
318 * Build a SHA-1/MD5 hash of the original message
319 * + the signature message(-digest) + key
321 * Then add the signature message to the packet and
325 add_signature(uint8_t * pck, int *size)
327 struct s_olsrmsg *msg;
331 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Adding signature for packet size %d\n", *size);
333 msg = (struct s_olsrmsg *)(ARM_NOWARN_ALIGN)&pck[*size];
335 ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
337 /* Fill packet header */
338 msg->olsr_msgtype = MESSAGE_TYPE;
340 msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
341 memcpy(&msg->originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
344 msg->seqno = htons(get_msg_seqno());
347 msg->sig.type = ONE_CHECKSUM;
348 msg->sig.algorithm = SCHEME;
349 memset(&msg->sig.reserved, 0, 2);
352 msg->sig.timestamp = htonl(now.tv_sec);
353 OLSR_DEBUG(LOG_PLUGINS, "[ENC]timestamp: %ld\n", (long)now.tv_sec);
355 /* Set the new size */
356 *size += sizeof(struct s_olsrmsg);
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);
364 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
366 /* Create the hash */
367 CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
374 const uint8_t *sigmsg;
375 OLSR_PRINTF(1, "Signature message:\n");
378 sigmsg = (uint8_t *) msg;
380 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
381 OLSR_PRINTF(1, " %3i", sigmsg[i]);
384 OLSR_PRINTF(1, "\n");
391 OLSR_DEBUG(LOG_PLUGINS, "[ENC] Message signed\n");
399 validate_packet(struct interface *olsr_if_config, const char *pck, int *size)
402 uint8_t sha1_hash[SIGNATURE_SIZE];
403 const struct s_olsrmsg *sig;
406 /* Find size - signature message */
407 packetsize = *size - sizeof(struct s_olsrmsg);
412 sig = (const struct s_olsrmsg *)(const ARM_NOWARN_ALIGN)&pck[packetsize];
414 //OLSR_PRINTF(1, "Size: %d\n", packetsize);
420 const uint8_t *sigmsg;
421 OLSR_PRINTF(1, "Input message:\n");
424 sigmsg = (const uint8_t *)sig;
426 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
427 OLSR_PRINTF(1, " %3i", sigmsg[i]);
430 OLSR_PRINTF(1, "\n");
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");
444 /* Check scheme and type */
445 switch (sig->sig.type) {
447 switch (sig->sig.algorithm) {
449 goto one_checksum_SHA; /* Ahhh... fix this */
456 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
459 //OLSR_PRINTF(1, "Packet sane...\n");
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);
469 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
472 CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
476 OLSR_PRINTF(1, "Recevied hash:\n");
478 sigmsg = (const uint8_t *)sig->sig.signature;
480 for (i = 0; i < SIGNATURE_SIZE; i++) {
481 OLSR_PRINTF(1, " %3i", sigmsg[i]);
483 OLSR_PRINTF(1, "\n");
485 OLSR_PRINTF(1, "Calculated hash:\n");
489 for (i = 0; i < SIGNATURE_SIZE; i++) {
490 OLSR_PRINTF(1, " %3i", sigmsg[i]);
492 OLSR_PRINTF(1, "\n");
495 if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
496 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch\n");
500 /* Check timestamp */
501 rec_time = ntohl(sig->sig.timestamp);
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;
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));
512 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Received timestamp %ld diff: %ld\n", (long)rec_time,
513 (long)now.tv_sec - (long)rec_time);
515 /* Remove signature message */
522 check_timestamp(struct interface *olsr_if_config, const union olsr_ip_addr *originator, time_t tstamp)
527 entry = lookup_timestamp_entry(originator);
530 /* Initiate timestamp negotiation */
532 send_challenge(olsr_if_config, originator);
537 if (!entry->validated) {
538 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Message from non-validated host!\n");
542 diff = entry->diff - (now.tv_sec - tstamp);
544 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp slack: %d\n", diff);
546 if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
547 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp scew detected!!\n");
551 /* ok - update diff */
552 entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
554 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Diff set to : %d\n", entry->diff);
556 /* update validtime */
558 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
565 * Create and send a timestamp
566 * challenge message to new_host
568 * The host is registered in the timestamps
569 * repository with valid=0
573 send_challenge(struct interface *olsr_if_config, const union olsr_ip_addr *new_host)
575 struct challengemsg cmsg;
577 uint32_t challenge, hash;
578 #if !defined REMOVE_LOG_DEBUG
579 struct ipaddr_str buf;
582 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building CHALLENGE message\n");
584 /* Set the size including OLSR packet size */
587 challenge = rand() << 16;
590 /* Fill challengemessage */
591 cmsg.olsr_msgtype = TYPE_CHALLENGE;
593 cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
594 memcpy(&cmsg.originator, &olsr_cnf->router_id, olsr_cnf->ipsize);
597 cmsg.seqno = htons(get_msg_seqno());
600 memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
601 cmsg.challenge = htonl(challenge);
603 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
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);
611 memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
613 /* Create the hash */
614 CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, cmsg.signature);
616 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending timestamp request to %s challenge 0x%x\n", olsr_ip_to_string(&buf, new_host), challenge);
619 net_outbuffer_push(olsr_if_config, &cmsg, sizeof(struct challengemsg));
621 /* Send the request */
622 net_output(olsr_if_config);
624 /* Create new entry */
625 entry = malloc(sizeof(struct stamp));
628 entry->validated = 0;
629 entry->challenge = challenge;
631 memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
633 /* update validtime - not validated */
634 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
636 hash = olsr_ip_hashing(new_host);
639 timestamps[hash].next->prev = entry;
640 entry->next = timestamps[hash].next;
641 timestamps[hash].next = entry;
642 entry->prev = ×tamps[hash];
650 parse_cres(struct interface *olsr_if_config, char *in_msg)
652 struct c_respmsg *msg;
653 uint8_t sha1_hash[SIGNATURE_SIZE];
655 #if !defined REMOVE_LOG_DEBUG
656 struct ipaddr_str buf;
659 msg = (struct c_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
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));
664 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
665 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
669 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
671 /* Check signature */
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);
679 memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
681 /* Create the hash */
682 CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
685 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
686 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in challenge-response!\n");
690 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
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));
700 /* Generate the digest */
701 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
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);
710 /* Create the hash */
711 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
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));
721 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response signature ok\n");
726 entry->challenge = 0;
727 entry->validated = 1;
728 entry->diff = now.tv_sec - msg->timestamp;
730 /* update validtime - validated entry */
731 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
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);
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));
744 parse_rres(char *in_msg)
746 struct r_respmsg *msg;
747 uint8_t sha1_hash[SIGNATURE_SIZE];
749 #if !defined REMOVE_LOG_DEBUG
750 struct ipaddr_str buf;
753 msg = (struct r_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
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));
758 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
759 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
763 /* Check signature */
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);
771 memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
773 /* Create the hash */
774 CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
777 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
778 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in response-response!\n");
782 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
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));
792 /* Generate the digest */
793 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
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);
802 /* Create the hash */
803 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
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));
813 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response signature ok\n");
818 entry->challenge = 0;
819 entry->validated = 1;
820 entry->diff = now.tv_sec - msg->timestamp;
822 /* update validtime - validated entry */
823 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
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);
833 parse_challenge(struct interface *olsr_if_config, char *in_msg)
835 struct challengemsg *msg;
836 uint8_t sha1_hash[SIGNATURE_SIZE];
839 #if !defined REMOVE_LOG_DEBUG
840 struct ipaddr_str buf;
843 msg = (struct challengemsg *)(ARM_NOWARN_ALIGN)in_msg;
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));
848 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
849 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Not for us...\n");
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);
858 hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
861 timestamps[hash].next->prev = entry;
862 entry->next = timestamps[hash].next;
863 timestamps[hash].next = entry;
864 entry->prev = ×tamps[hash];
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");
872 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge from registered node...accepted!\n");
876 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
878 /* Check signature */
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);
886 memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
888 /* Create the hash */
889 CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
891 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
892 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature missmatch in challenge!\n");
896 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Signature verified\n");
900 entry->validated = 0;
902 /* update validtime - not validated */
903 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
905 /* Build and send response */
907 send_cres(olsr_if_config, (union olsr_ip_addr *)&msg->originator,
908 (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry);
918 * Build and transmit a challenge response
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)
925 struct c_respmsg crmsg;
927 #if !defined REMOVE_LOG_DEBUG
928 struct ipaddr_str buf;
931 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building CRESPONSE message\n");
933 challenge = rand() << 16;
936 entry->challenge = challenge;
938 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Challenge-response: 0x%x\n", challenge);
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);
947 crmsg.seqno = htons(get_msg_seqno());
950 crmsg.timestamp = now.tv_sec;
951 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp %ld\n", (long)crmsg.timestamp);
954 memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
955 crmsg.challenge = htonl(challenge);
957 /* Create digest of received challenge + IP */
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);
967 /* Create the hash */
968 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, crmsg.res_sig);
971 /* Now create the digest of the message and the key */
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);
979 memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
981 /* Create the hash */
982 CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, crmsg.signature);
985 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
988 net_outbuffer_push(olsr_if_config, &crmsg, sizeof(struct c_respmsg));
989 /* Send the request */
990 net_output(olsr_if_config);
1001 * Build and transmit a response response
1006 send_rres(struct interface *olsr_if_config, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
1008 struct r_respmsg rrmsg;
1009 #if !defined REMOVE_LOG_DEBUG
1010 struct ipaddr_str buf;
1013 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Building RRESPONSE message\n");
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);
1023 rrmsg.seqno = htons(get_msg_seqno());
1026 rrmsg.timestamp = now.tv_sec;
1027 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Timestamp %ld\n", (long)rrmsg.timestamp);
1029 /* Fill subheader */
1030 memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
1032 /* Create digest of received challenge + IP */
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);
1042 /* Create the hash */
1043 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, rrmsg.res_sig);
1046 /* Now create the digest of the message and the key */
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);
1054 memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
1056 /* Create the hash */
1057 CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, rrmsg.signature);
1060 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1063 net_outbuffer_push(olsr_if_config, &rrmsg, sizeof(struct r_respmsg));
1065 /* Send the request */
1066 net_output(olsr_if_config);
1073 static struct stamp *
1074 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1077 struct stamp *entry;
1078 #if !defined REMOVE_LOG_DEBUG
1079 struct ipaddr_str buf;
1082 hash = olsr_ip_hashing(adr);
1084 for (entry = timestamps[hash].next; entry != ×tamps[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));
1091 OLSR_DEBUG(LOG_PLUGINS, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1099 *Find timed out entries and delete them
1104 timeout_timestamps(void *foo __attribute__ ((unused)))
1106 struct stamp *tmp_list;
1107 struct stamp *entry_to_delete;
1110 /* Update our local timestamp */
1111 gettimeofday(&now, NULL);
1113 for (idx = 0; idx < HASHSIZE; idx++) {
1114 tmp_list = timestamps[idx].next;
1115 /*Traverse MID list */
1116 while (tmp_list != ×tamps[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;
1122 entry_to_delete = tmp_list;
1123 tmp_list = tmp_list->next;
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));
1129 entry_to_delete->next->prev = entry_to_delete->prev;
1130 entry_to_delete->prev->next = entry_to_delete->next;
1132 free(entry_to_delete);
1134 tmp_list = tmp_list->next;
1144 read_key_from_file(const char *file)
1150 kf = fopen(file, "r");
1152 OLSR_DEBUG(LOG_PLUGINS, "[ENC]Reading key from file \"%s\"\n", file);
1155 OLSR_WARN(LOG_PLUGINS, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
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));
1174 * indent-tabs-mode: nil