6 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
19 * * Neither the name of olsrd, olsr.org nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
38 /* Adjustments made to ensure data going out is converted to network
39 * byte ordering. Also, to ensure incoming data is converted before
40 * it is used and before checksums are calculated as well.
41 * Rusty Haddock AE5AE -- for the HSMM-MESH project.
45 * Dynamic linked library for the olsr.org olsr daemon
48 #include "olsrd_secure.h"
62 #include "scheduler.h"
68 #include <openssl/sha.h>
71 #define SCHEME SHA1_INCLUDING_KEY
73 #else /* USE_OPENSSL */
75 /* Homebrewn checksuming */
79 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
84 MD5Update(&context, data, data_len);
85 MD5Final(hashbuf, &context);
88 #define CHECKSUM MD5_checksum
89 #define SCHEME MD5_INCLUDING_KEY
91 #endif /* USE_OPENSSL */
98 #define close(x) closesocket(x)
100 #define EWOULDBLOCK WSAEWOULDBLOCK
104 #define OS "GNU/Linux"
105 #endif /* __linux__ */
106 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
108 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ */
111 #define OS "Undefined"
114 static struct timeval now;
118 union olsr_ip_addr addr;
119 /* Timestamp difference */
123 uint32_t valtime; /* Validity time */
124 uint32_t conftime; /* Reconfiguration time */
129 /* Seconds to cache a valid timestamp entry */
130 #define TIMESTAMP_HOLD_TIME 30
132 /* Seconds to cache a not verified timestamp entry */
133 #define EXCHANGE_HOLD_TIME 5
135 static struct stamp timestamps[HASHSIZE];
137 char keyfile[FILENAME_MAX + 1];
140 /* Event function to register with the sceduler */
141 static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
142 static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
143 static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
144 static int parse_challenge(struct interface *olsr_if, char *);
145 static int parse_cres(struct interface *olsr_if, char *);
146 static int parse_rres(char *);
147 static int check_auth(struct interface *olsr_if, char *, int *);
148 static int add_signature(uint8_t *, int *);
149 static int validate_packet(struct interface *olsr_if, const char *, int *);
150 static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
151 static void timeout_timestamps(void *);
152 static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
153 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
154 static int read_key_from_file(const char *);
157 *Do initialization here
159 *This function is called by the my_init
160 *function in uolsrd_plugin.c
164 secure_plugin_init(void)
168 /* Initialize the timestamp database */
169 for (i = 0; i < HASHSIZE; i++) {
170 timestamps[i].next = ×tamps[i];
171 timestamps[i].prev = ×tamps[i];
173 olsr_printf(1, "Timestamp database initialized\n");
175 if (!strlen(keyfile))
176 strscpy(keyfile, KEYFILE, sizeof(keyfile));
178 i = read_key_from_file(keyfile);
181 olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
185 olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
189 /* Register the packet transform function */
190 add_ptf(&add_signature);
192 olsr_preprocessor_add_function(&secure_preprocessor);
194 /* Register timeout - poll every 2 seconds */
195 olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &timeout_timestamps, NULL, 0);
201 plugin_ipc_init(void)
207 * destructor - called at unload
210 secure_plugin_exit(void)
212 olsr_preprocessor_remove_function(&secure_preprocessor);
216 secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
218 struct olsr *olsr = (struct olsr *)packet;
219 struct ipaddr_str buf;
222 * Check for challenge/response messages
224 check_auth(olsr_if, packet, length);
230 if (!validate_packet(olsr_if, packet, length)) {
231 olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
235 olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
237 /* Fix OLSR packet header */
238 olsr->olsr_packlen = htons(*length);
243 * Check a incoming OLSR packet for
244 * challenge/responses.
245 * They need not be verified as they
246 * are signed in the message.
250 check_auth(struct interface *olsr_if, char *pck, int *size __attribute__ ((unused)))
253 olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
256 case (TYPE_CHALLENGE):
257 parse_challenge(olsr_if, &pck[4]);
260 case (TYPE_CRESPONSE):
261 parse_cres(olsr_if, &pck[4]);
264 case (TYPE_RRESPONSE):
276 * Packet transform function
277 * Build a SHA-1/MD5 hash of the original message
278 * + the signature message(-digest) + key
280 * Then add the signature message to the packet and
284 add_signature(uint8_t * pck, int *size)
286 struct s_olsrmsg *msg;
290 const uint8_t *sigmsg;
293 olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
296 msg = (struct s_olsrmsg *)ARM_NOWARN_ALIGN(&pck[*size]);
298 ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
300 /* Fill packet header */
301 msg->olsr_msgtype = MESSAGE_TYPE;
303 msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
304 memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
307 msg->seqno = htons(get_msg_seqno());
310 msg->sig.type = ONE_CHECKSUM;
311 msg->sig.algorithm = SCHEME;
312 memset(&msg->sig.reserved, 0, 2);
315 msg->sig.timestamp = htonl(now.tv_sec);
317 olsr_printf(3, "[ENC]timestamp: %lld\n", (long long)now.tv_sec);
319 /* Set the new size */
320 *size += sizeof(struct s_olsrmsg);
323 uint8_t checksum_cache[1512 + KEYLENGTH];
324 /* Create packet + key cache */
325 /* First the OLSR packet + signature message - digest */
326 memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
328 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
330 /* Create the hash */
331 CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
335 olsr_printf(1, "Signature message:\n");
338 sigmsg = (uint8_t *) msg;
340 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
341 olsr_printf(1, " %3i", sigmsg[i]);
344 olsr_printf(1, "\n");
350 olsr_printf(3, "[ENC] Message signed\n");
356 validate_packet(struct interface *olsr_if, const char *pck, int *size)
359 uint8_t sha1_hash[SIGNATURE_SIZE];
360 const struct s_olsrmsg *sig;
366 const uint8_t *sigmsg;
369 /* Find size - signature message */
370 packetsize = *size - sizeof(struct s_olsrmsg);
375 sig = (const struct s_olsrmsg *)CONST_ARM_NOWARN_ALIGN(&pck[packetsize]);
377 //olsr_printf(1, "Size: %d\n", packetsize);
380 olsr_printf(1, "Input message:\n");
383 sigmsg = (const uint8_t *)sig;
385 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
386 olsr_printf(1, " %3i", sigmsg[i]);
389 olsr_printf(1, "\n");
395 /* Sanity check first */
396 if ((sig->olsr_msgtype != MESSAGE_TYPE) || (sig->olsr_vtime != 0)
397 || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
398 olsr_printf(1, "[ENC]Packet not sane!\n");
402 /* Check scheme and type */
403 switch (sig->sig.type) {
405 switch (sig->sig.algorithm) {
407 goto one_checksum_SHA; /* Ahhh... fix this */
415 olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
418 //olsr_printf(1, "Packet sane...\n");
423 uint8_t checksum_cache[1512 + KEYLENGTH];
424 /* Create packet + key cache */
425 /* First the OLSR packet + signature message - digest */
426 memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
428 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
431 CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
435 olsr_printf(1, "Recevied hash:\n");
437 sigmsg = (const uint8_t *)sig->sig.signature;
439 for (i = 0; i < SIGNATURE_SIZE; i++) {
440 olsr_printf(1, " %3i", sigmsg[i]);
442 olsr_printf(1, "\n");
444 olsr_printf(1, "Calculated hash:\n");
448 for (i = 0; i < SIGNATURE_SIZE; i++) {
449 olsr_printf(1, " %3i", sigmsg[i]);
451 olsr_printf(1, "\n");
454 if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
455 olsr_printf(1, "[ENC]Signature missmatch\n");
459 /* Check timestamp */
460 rec_time = ntohl(sig->sig.timestamp);
462 if (!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
463 struct ipaddr_str buf;
464 olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
465 olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
469 olsr_printf(1, "[ENC]Received timestamp %lld diff: %lld\n", (long long)rec_time, (long long)now.tv_sec - (long long)rec_time);
471 /* Remove signature message */
477 check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
482 entry = lookup_timestamp_entry(originator);
485 /* Initiate timestamp negotiation */
487 send_challenge(olsr_if, originator);
492 if (!entry->validated) {
493 olsr_printf(1, "[ENC]Message from non-validated host!\n");
497 diff = entry->diff - (now.tv_sec - tstamp);
499 olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
501 if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
502 olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
506 /* ok - update diff */
507 entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
509 olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
511 /* update validtime */
513 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
519 * Create and send a timestamp
520 * challenge message to new_host
522 * The host is registered in the timestamps
523 * repository with valid=0
527 send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
529 struct challengemsg cmsg;
531 uint32_t challenge, hash;
532 struct ipaddr_str buf;
534 olsr_printf(1, "[ENC]Building CHALLENGE message\n");
536 /* Set the size including OLSR packet size */
538 challenge = rand() << 16;
541 /* initialise rrmsg */
542 memset(&cmsg, 0, sizeof(cmsg));
544 /* Fill challengemessage */
545 cmsg.olsr_msgtype = TYPE_CHALLENGE;
546 cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
547 memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
549 cmsg.seqno = htons(get_msg_seqno());
552 assert(olsr_cnf->ipsize == sizeof(cmsg.destination));
553 memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
554 cmsg.challenge = htonl(challenge);
556 olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
559 uint8_t checksum_cache[(sizeof(cmsg) - sizeof(cmsg.signature)) + KEYLENGTH];
560 /* Create packet + key cache */
561 /* First the OLSR packet + signature message - digest */
562 memcpy(checksum_cache, &cmsg, sizeof(cmsg) - sizeof(cmsg.signature));
564 memcpy(&checksum_cache[sizeof(cmsg) - sizeof(cmsg.signature)], aes_key, KEYLENGTH);
566 /* Create the hash */
567 CHECKSUM(checksum_cache, (sizeof(cmsg) - sizeof(cmsg.signature)) + KEYLENGTH, cmsg.signature);
569 olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n",
570 olsr_ip_to_string(&buf, new_host), challenge);
573 net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
575 /* Send the request */
578 /* Create new entry */
579 entry = malloc(sizeof(struct stamp));
582 entry->validated = 0;
583 entry->challenge = challenge;
585 memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
587 /* update validtime - not validated */
588 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
590 hash = olsr_ip_hashing(new_host);
593 timestamps[hash].next->prev = entry;
594 entry->next = timestamps[hash].next;
595 timestamps[hash].next = entry;
596 entry->prev = ×tamps[hash];
603 parse_cres(struct interface *olsr_if, char *in_msg)
605 struct c_respmsg *msg;
606 uint8_t sha1_hash[SIGNATURE_SIZE];
608 struct ipaddr_str buf;
610 msg = (struct c_respmsg *)ARM_NOWARN_ALIGN(in_msg);
612 olsr_printf(1, "[ENC]Challenge-response message received\n");
613 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
615 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
616 olsr_printf(3, "[ENC]Not for us...\n");
620 olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
622 /* Check signature */
625 uint8_t checksum_cache[1512 + KEYLENGTH];
626 /* Create packet + key cache */
627 /* First the OLSR packet + signature message - digest */
628 memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
630 memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
632 /* Create the hash */
633 CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
636 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
637 olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
641 olsr_printf(3, "[ENC]Signature verified\n");
643 /* Now to check the digest from the emitted challenge */
644 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
645 olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
646 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
650 /* Generate the digest */
651 olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
654 uint8_t checksum_cache[1512 + KEYLENGTH];
655 uint32_t netorder_challenge;
657 /* First the challenge received */
658 /* But we have to calculate our hash with the challenge in
659 * network order just like the remote host did! 6-Jun-2011 AE5AE */
660 netorder_challenge = htonl(entry->challenge);
661 memcpy(checksum_cache, &netorder_challenge, sizeof(uint32_t));
662 /* memcpy(checksum_cache, &entry->challenge, 4); */
664 /* Then the local IP */
665 memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
667 /* Create the hash */
668 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
671 if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
672 olsr_printf(1, "[ENC]Error in challenge signature from %s!\n",
673 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
678 olsr_printf(3, "[ENC]Challenge-response signature ok\n");
682 entry->challenge = 0;
683 entry->validated = 1;
685 /* Bring timestamp to host order before arith. 2011/05/31 AE5AE */
686 entry->diff = now.tv_sec - ntohl(msg->timestamp);
688 /* update validtime - validated entry */
689 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
691 olsr_printf(1, "[ENC]%s registered with diff %d!\n",
692 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
695 /* Send response-response */
696 send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator,
697 (union olsr_ip_addr *)&msg->destination, msg->challenge);
698 /* (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge)); */
699 /* Don't give send_rres() the challenge in host order, as the checksum needs to
700 * be calculated in network order. 06-Jun-2011 AE5AE */
706 parse_rres(char *in_msg)
708 struct r_respmsg *msg;
709 uint8_t sha1_hash[SIGNATURE_SIZE];
711 struct ipaddr_str buf;
713 msg = (struct r_respmsg *)ARM_NOWARN_ALIGN(in_msg);
715 olsr_printf(1, "[ENC]Response-response message received\n");
716 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
718 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
719 olsr_printf(1, "[ENC]Not for us...\n");
723 /* Check signature */
726 uint8_t checksum_cache[1512 + KEYLENGTH];
727 /* Create packet + key cache */
728 /* First the OLSR packet + signature message - digest */
729 memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
731 memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
733 /* Create the hash */
734 CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
737 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
738 olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
742 olsr_printf(3, "[ENC]Signature verified\n");
744 /* Now to check the digest from the emitted challenge */
745 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
746 olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
747 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
751 /* Generate the digest */
752 olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
755 uint8_t checksum_cache[1512 + KEYLENGTH];
756 uint32_t netorder_challenge;
758 /* First the challenge received */
759 /* But we have to calculate our hash with the challenge in network order! 6-Jun-2011 AE5AE */
760 netorder_challenge = htonl(entry->challenge);
761 memcpy(checksum_cache, &netorder_challenge, sizeof(uint32_t));
762 /* memcpy(checksum_cache, &entry->challenge, 4); */
764 /* Then the local IP */
765 memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
767 /* Create the hash */
768 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
771 if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
772 olsr_printf(1, "[ENC]Error in response signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
777 olsr_printf(3, "[ENC]Challenge-response signature ok\n");
781 entry->challenge = 0;
782 entry->validated = 1;
784 /* Bring timestamp to host order before arith. 2011/05/31 AE5AE */
785 entry->diff = now.tv_sec - ntohl(msg->timestamp);
788 /* update validtime - validated entry */
789 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
791 olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
798 parse_challenge(struct interface *olsr_if, char *in_msg)
800 struct challengemsg *msg;
801 uint8_t sha1_hash[SIGNATURE_SIZE];
804 struct ipaddr_str buf;
806 msg = (struct challengemsg *)ARM_NOWARN_ALIGN(in_msg);
808 olsr_printf(1, "[ENC]Challenge message received\n");
809 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
811 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
812 olsr_printf(1, "[ENC]Not for us...\n");
816 /* Create entry if not registered */
817 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
818 entry = malloc(sizeof(struct stamp));
819 memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
821 hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
824 timestamps[hash].next->prev = entry;
825 entry->next = timestamps[hash].next;
826 timestamps[hash].next = entry;
827 entry->prev = ×tamps[hash];
829 /* Check configuration timeout */
830 if (!TIMED_OUT(entry->conftime)) {
831 /* If registered - do not accept! */
832 olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
835 olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
839 olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
841 /* Check signature */
844 uint8_t checksum_cache[1512 + KEYLENGTH];
845 /* Create packet + key cache */
846 /* First the OLSR packet + signature message - digest */
847 memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
849 memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
851 /* Create the hash */
852 CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
854 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
855 olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
859 olsr_printf(3, "[ENC]Signature verified\n");
862 entry->validated = 0;
864 /* update validtime - not validated */
865 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
867 /* Build and send response */
869 send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator,
870 (union olsr_ip_addr *)&msg->destination, msg->challenge, entry);
871 /* (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry); */
872 /* Don't give send_cres() the challenge in host order, as the checksum needs to
873 * be calculated with network order. 06-Jun-2011 AE5AE */
879 * Build and transmit a challenge response
884 send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
886 struct c_respmsg crmsg;
888 struct ipaddr_str buf;
890 olsr_printf(1, "[ENC]Building CRESPONSE message\n");
892 challenge = rand() << 16;
895 entry->challenge = challenge;
897 olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
899 /* initialise rrmsg */
900 memset(&crmsg, 0, sizeof(crmsg));
902 /* Fill challengemessage */
903 crmsg.olsr_msgtype = TYPE_CRESPONSE;
904 crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
905 memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
907 crmsg.seqno = htons(get_msg_seqno());
910 /* but swap the byte order to the network order before sending! 2011/05/28 AE5AE */
911 crmsg.timestamp = htonl(now.tv_sec);
913 /* Don't print htonl()'d time, use now.tv_sec 2011/05/31 AE5AE */
914 /* olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)crmsg.timestamp); */
915 olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)now.tv_sec);
919 assert(olsr_cnf->ipsize == sizeof(crmsg.destination));
920 memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
921 crmsg.challenge = htonl(challenge);
923 /* Create digest of received challenge + IP */
926 uint8_t checksum_cache[sizeof(chal_in) + olsr_cnf->ipsize];
927 /* Create packet + key cache */
928 /* First the challenge received */
929 memcpy(checksum_cache, &chal_in, sizeof(chal_in));
930 /* Then the local IP */
931 memcpy(&checksum_cache[sizeof(chal_in)], from, olsr_cnf->ipsize);
933 /* Create the hash */
934 CHECKSUM(checksum_cache, sizeof(chal_in) + olsr_cnf->ipsize, crmsg.res_sig);
937 /* Now create the digest of the message and the key */
940 uint8_t checksum_cache[(sizeof(crmsg) - sizeof(crmsg.signature)) + KEYLENGTH];
941 /* Create packet + key cache */
942 /* First the OLSR packet + signature message - digest */
943 memcpy(checksum_cache, &crmsg, sizeof(crmsg) - sizeof(crmsg.signature));
945 memcpy(&checksum_cache[sizeof(crmsg) - sizeof(crmsg.signature)], aes_key, KEYLENGTH);
947 /* Create the hash */
948 CHECKSUM(checksum_cache, (sizeof(crmsg) - sizeof(crmsg.signature)) + KEYLENGTH, crmsg.signature);
951 olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
954 net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
955 /* Send the request */
962 * Build and transmit a response response
967 send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
969 struct r_respmsg rrmsg;
970 struct ipaddr_str buf;
972 olsr_printf(1, "[ENC]Building RRESPONSE message\n");
974 /* initialise rrmsg */
975 memset(&rrmsg, 0, sizeof(rrmsg));
977 /* Fill challengemessage */
978 rrmsg.olsr_msgtype = TYPE_RRESPONSE;
979 rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
980 memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
982 rrmsg.seqno = htons(get_msg_seqno());
985 /* But swap the byte order to the network order! 2011/05/28 AE5AE */
986 rrmsg.timestamp = htonl(now.tv_sec);
989 /* olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)rrmsg.timestamp); */
990 /* don't print htonl()'d time, use now. 2011/05/31 AE5AE */
991 olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)now.tv_sec);
994 assert(olsr_cnf->ipsize == sizeof(rrmsg.destination));
995 memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
997 /* Create digest of received challenge + IP */
1000 uint8_t checksum_cache[sizeof(chal_in) + sizeof(union olsr_ip_addr)];
1001 /* Create packet + key cache */
1002 /* First the challenge received */
1003 memcpy(checksum_cache, &chal_in, sizeof(chal_in));
1004 /* Then the local IP */
1005 memcpy(&checksum_cache[sizeof(chal_in)], from, olsr_cnf->ipsize);
1007 /* Create the hash */
1008 CHECKSUM(checksum_cache, sizeof(chal_in) + olsr_cnf->ipsize, rrmsg.res_sig);
1011 /* Now create the digest of the message and the key */
1014 uint8_t checksum_cache[(sizeof(rrmsg) - sizeof(rrmsg.signature)) + KEYLENGTH];
1015 /* Create packet + key cache */
1016 /* First the OLSR packet + signature message - digest */
1017 memcpy(checksum_cache, &rrmsg, sizeof(rrmsg) - sizeof(rrmsg.signature));
1019 memcpy(&checksum_cache[sizeof(rrmsg) - sizeof(rrmsg.signature)], aes_key, KEYLENGTH);
1021 /* Create the hash */
1022 CHECKSUM(checksum_cache, (sizeof(rrmsg) - sizeof(rrmsg.signature)) + KEYLENGTH, rrmsg.signature);
1025 olsr_printf(3, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1028 net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
1030 /* Send the request */
1031 net_output(olsr_if);
1036 static struct stamp *
1037 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1040 struct stamp *entry;
1041 struct ipaddr_str buf;
1043 hash = olsr_ip_hashing(adr);
1045 for (entry = timestamps[hash].next; entry != ×tamps[hash]; entry = entry->next) {
1046 if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1047 olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1052 olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1058 *Find timed out entries and delete them
1063 timeout_timestamps(void *foo __attribute__ ((unused)))
1065 struct stamp *tmp_list;
1066 struct stamp *entry_to_delete;
1069 /* Update our local timestamp */
1070 gettimeofday(&now, NULL);
1072 for (idx = 0; idx < HASHSIZE; idx++) {
1073 tmp_list = timestamps[idx].next;
1074 /*Traverse MID list */
1075 while (tmp_list != ×tamps[idx]) {
1076 /*Check if the entry is timed out */
1077 if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1078 struct ipaddr_str buf;
1079 entry_to_delete = tmp_list;
1080 tmp_list = tmp_list->next;
1082 olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n",
1083 olsr_ip_to_string(&buf, &entry_to_delete->addr));
1086 entry_to_delete->next->prev = entry_to_delete->prev;
1087 entry_to_delete->prev->next = entry_to_delete->next;
1089 free(entry_to_delete);
1091 tmp_list = tmp_list->next;
1099 read_key_from_file(const char *file)
1105 kf = fopen(file, "r");
1107 olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
1110 olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1114 if (fread(aes_key, 1, keylen, kf) != keylen) {
1115 olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1127 * indent-tabs-mode: nil