📄 olsrd_secure.c
字号:
/* * Secure OLSR plugin * http://www.olsr.org * * Copyright (c) 2004, Andreas T鴑nesen(andreto@olsr.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of olsrd, olsr.org nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: olsrd_secure.c,v 1.27 2007/08/02 14:37:09 bernd67 Exp $ *//* * Dynamic linked library for the olsr.org olsr daemon */#include "olsrd_secure.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#ifdef linux#include <linux/in_route.h>#endif#include <unistd.h>#include <errno.h>#include <signal.h>#include "defs.h"#include "olsr.h"#include "socket_parser.h"#include "parser.h"#include "scheduler.h"#ifdef USE_OPENSSL/* OpenSSL stuff */#include <openssl/sha.h>#define CHECKSUM SHA1#define SCHEME SHA1_INCLUDING_KEY#else/* Homebrewn checksuming */#include "md5.h"static voidMD5_checksum(const olsr_u8_t *data, const olsr_u16_t data_len, olsr_u8_t *hashbuf){ MD5_CTX context; MD5Init(&context); MD5Update(&context, data, data_len); MD5Final(hashbuf, &context);}#define CHECKSUM MD5_checksum#define SCHEME MD5_INCLUDING_KEY#endif#ifdef OS#undef OS#endif#ifdef WIN32#define close(x) closesocket(x)#undef EWOULDBLOCK#define EWOULDBLOCK WSAEWOULDBLOCK#define OS "Windows"#endif#ifdef linux#define OS "GNU/Linux"#endif#ifdef __FreeBSD__#define OS "FreeBSD"#endif#ifndef OS#define OS "Undefined"#endif/* Timestamp node */struct stamp{ union olsr_ip_addr addr; /* Timestamp difference */ int diff; olsr_u32_t challenge; olsr_u8_t validated; clock_t valtime; /* Validity time */ clock_t conftime; /* Reconfiguration time */ struct stamp *prev; struct stamp *next;};/* Seconds to cache a valid timestamp entry */#define TIMESTAMP_HOLD_TIME 30/* Seconds to cache a not verified timestamp entry */#define EXCHANGE_HOLD_TIME 5static struct stamp timestamps[HASHSIZE];char keyfile[FILENAME_MAX+1];char aes_key[16];/* Input interface */static struct interface *olsr_in_if;/* Event function to register with the sceduler */#if 0static void olsr_event(void);#endifstatic int send_challenge(union olsr_ip_addr *);static int ifchange(struct interface *, int);static int send_cres(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t, struct stamp *);static int send_rres(union olsr_ip_addr *, union olsr_ip_addr *, olsr_u32_t);static int parse_challenge(char *);static int parse_cres(char *);static int parse_rres(char *);static int check_auth(char *, int *);#if 0static int ipc_send(char *, int);#endifstatic int add_signature(olsr_u8_t *, int*);static int validate_packet(char *, int*);static void packet_parser(int);static void timeout_timestamps(void*);static int check_timestamp(union olsr_ip_addr *, time_t);static struct stamp *lookup_timestamp_entry(union olsr_ip_addr *);static int read_key_from_file(char *);/** *Do initialization here * *This function is called by the my_init *function in uolsrd_plugin.c */intsecure_plugin_init(void){ struct interface *ints; int i; /* Initialize the timestamp database */ for(i = 0; i < HASHSIZE; i++) { timestamps[i].next = ×tamps[i]; timestamps[i].prev = ×tamps[i]; } olsr_printf(1, "Timestamp database initialized\n"); if(!strlen(keyfile)) strcpy(keyfile, KEYFILE); i = read_key_from_file(keyfile); if(i < 0) { olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile); exit(1); } if(i == 0) { olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile); exit(1); } /* Register the packet transform function */ add_ptf(&add_signature); /* register ifchange function */ add_ifchgf(&ifchange); /* Hijack OLSR socket parser functions */ ints = ifnet; while(ints) { olsr_printf(1, "[ENC]Hijacking %s socket %d\n", ints->int_name, ints->olsr_socket); fflush(stdout); remove_olsr_socket(ints->olsr_socket, olsr_input); add_olsr_socket(ints->olsr_socket, &packet_parser); /* Reducing maxmessagesize */ net_reserve_bufspace(ints, sizeof(struct s_olsrmsg)); ints = ints->int_next; } /* Register timeout - poll every 2 seconds */ olsr_register_scheduler_event(&timeout_timestamps, NULL, 2, 0 , NULL); return 1;}intplugin_ipc_init(void){ return 1;}/* * destructor - called at unload */voidsecure_plugin_exit(void){}#if 0/** *Scheduled event */static voidolsr_event(void){}#endif#if 0static intipc_send(char *data __attribute__((unused)), int size __attribute__((unused))){ return 1;}#endif/* XXX - ToDo */static intifchange(struct interface *ifn, int action){ switch(action) { case(IFCHG_IF_ADD): printf("SEC: interface %s added\n\n", ifn->int_name); olsr_printf(1, "[ENC]Hijacking %s socket %d\n", ifn->int_name, ifn->olsr_socket); remove_olsr_socket(ifn->olsr_socket, olsr_input); add_olsr_socket(ifn->olsr_socket, &packet_parser); /* Reducing maxmessagesize */ net_reserve_bufspace(ifn, sizeof(struct s_olsrmsg)); break; case(IFCHG_IF_REMOVE): printf("SEC: interface %s removed\n\n", ifn->int_name); olsr_printf(1, "[ENC]Removing %s socket %d\n", ifn->int_name, ifn->olsr_socket); remove_olsr_socket(ifn->olsr_socket, &packet_parser); break; case(IFCHG_IF_UPDATE): printf("SEC: interface %s updated\n\n", ifn->int_name); break; default: break; } return 0; }static voidpacket_parser(int fd){ /* sockaddr_in6 is bigger than sockaddr !!!! */ struct sockaddr_storage from; socklen_t fromlen; int cc; union olsr_ip_addr from_addr; union { char buf[MAXMESSAGESIZE+1]; struct olsr olsr; } inbuf; for (;;) { fromlen = sizeof(struct sockaddr_storage); cc = recvfrom(fd, (void *)&inbuf, sizeof (inbuf), 0, (struct sockaddr *)&from, &fromlen); if (cc <= 0) { if (cc < 0 && errno != EWOULDBLOCK) { olsr_printf(1, "[ENC]error recvfrom: %s", strerror(errno)); } break; } if(olsr_cnf->ip_version == AF_INET) { /* IPv4 sender address */ memcpy(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr, olsr_cnf->ipsize); } else { /* IPv6 sender address */ memcpy(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr, olsr_cnf->ipsize); } /* olsr_printf(1, "[ENC]message from %s size %d\n", olsr_ip_to_string(&from_addr), cc); */ /* are we talking to ourselves? */ if(if_ifwithaddr(&from_addr) != NULL) return; /* *setting global from addr */ //printf("Recieved data on socket %d\n", socknr); if((olsr_in_if = if_ifwithsock(fd)) == NULL) { olsr_printf(1, "[ENC]Could not find input interface for message from %s size %d\n", olsr_ip_to_string(&from_addr), cc); return ; } /* * Check for challenge/response messages */ check_auth(inbuf.buf, &cc); /* * Check signature */ if(!validate_packet(inbuf.buf, &cc)) { olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr)); return; } olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr), cc); /* Fix OLSR packet header */ inbuf.olsr.olsr_packlen = htons(cc); //olsr_printf(1, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr)); //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen); if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in))) break; else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6))) break; /* * &from - sender * &inbuf.olsr * cc - bytes read */ parse_packet(&inbuf.olsr, cc, olsr_in_if, &from_addr); }}/** * Check a incoming OLSR packet for * challenge/responses. * They need not be verified as they * are signed in the message. * */static intcheck_auth(char *pck, int *size __attribute__((unused))){ olsr_printf(3, "[ENC]Checking packet for challenge response message...\n"); switch(pck[4]) { case(TYPE_CHALLENGE): parse_challenge(&pck[4]); break; case(TYPE_CRESPONSE): parse_cres(&pck[4]); break; case(TYPE_RRESPONSE): parse_rres(&pck[4]); break; default: return 0; } return 1;}/** * Packet transform function * Build a SHA-1/MD5 hash of the original message * + the signature message(-digest) + key * * Then add the signature message to the packet and * increase the size */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -