From 30dbbc65bd3684b9cefa000069b611a608f4be3e Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Mon, 3 Mar 2008 17:59:57 +0000 Subject: some bugfixes added support for authentication --- Makefile | 4 -- anyrtpproxy/anyrtpproxy.cpp | 140 ++++++++++++++++++-------------------------- anytun.cpp | 86 +++++++++++++++++---------- authAlgo.cpp | 82 ++++++++++++++++++-------- authAlgo.h | 42 +++++++++---- authTag.cpp | 49 ---------------- authTag.h | 54 ----------------- buffer.cpp | 10 +++- cipher.cpp | 18 +++--- cipher.h | 12 ++-- encryptedPacket.cpp | 122 ++++++++++++++++++++++---------------- encryptedPacket.h | 14 +++-- options.cpp | 19 +++++- options.h | 3 + plainPacket.cpp | 17 ++++-- 15 files changed, 339 insertions(+), 333 deletions(-) delete mode 100644 authTag.cpp delete mode 100644 authTag.h diff --git a/Makefile b/Makefile index 4fa58a8..e68e5e9 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,6 @@ OBJS = tunDevice.o \ encryptedPacket.o \ cipher.o \ authAlgo.o \ - authTag.o \ keyDerivation.o \ mpi.o \ cipherFactory.o \ @@ -160,9 +159,6 @@ anyctrOptions.o: anyctrOptions.cpp anyctrOptions.h authAlgo.o: authAlgo.cpp authAlgo.h buffer.h $(C++) $(CCFLAGS) $< -c -authTag.o: authTag.cpp authTag.h buffer.h - $(C++) $(CCFLAGS) $< -c - keyDerivation.o: keyDerivation.cpp keyDerivation.h $(C++) $(CCFLAGS) $< -c diff --git a/anyrtpproxy/anyrtpproxy.cpp b/anyrtpproxy/anyrtpproxy.cpp index 41cb643..9079994 100644 --- a/anyrtpproxy/anyrtpproxy.cpp +++ b/anyrtpproxy/anyrtpproxy.cpp @@ -12,61 +12,54 @@ #include "../buffer.h" #include "options.h" -#include +#include + #define MAX_PACKET_SIZE 1500 -class ControlHost +class ControlHost : public Host { public: - ControlHost() : host_("",0) {}; - - Host getHost() { - Lock lock(mutex); - return host_; - } - - void setHost(std::string addr, u_int16_t port) + ControlHost() : Host("",0) {}; + bool operator<(const ControlHost& cmp_to) { - Lock lock(mutex); - if(host_.addr_ != addr || host_.port_ != port) - cLog.msg(Log::PRIO_NOTICE) << "control Host detected at " << addr << ":" << port; - - host_.addr_ = addr; - host_.port_ = port; + return port_ < cmp_to.port_; } - -private: - Mutex mutex; - - Host host_; }; -struct ThreadParam +class ControlHostMap { - ControlHost& control_; - UDPSocket& control_sock_; - UDPSocket& sock_; - Host first_receiver_; -}; +public: + -void* sender(void* p) -{ - ThreadParam* param = reinterpret_cast(p); +private: + Mutex mutex; + + std::map> control_hosts_; +} +void* sender(void* dont_use_me) +{ try { HostList remote_host_list(gOpt.getRemoteHosts()); + UDPSocket control_sock(gOpt.getControlInterface().addr_, gOpt.getControlInterface().port_); Buffer buf(u_int32_t(MAX_PACKET_SIZE)); string remote_host; u_int16_t remote_port; while(1) { buf.setLength(MAX_PACKET_SIZE); - u_int32_t len = param->control_sock_.recvFrom(buf.getBuf(), buf.getLength(), remote_host, remote_port); + u_int32_t len = control_sock_.recvFrom(buf.getBuf(), buf.getLength(), remote_host, remote_port); buf.setLength(len); param->control_.setHost(remote_host, remote_port); + +// SenderThreadParam receiverParam = {control_host, control_sock, sock, gOpt.getRemoteHosts().front()}; +// pthread_t receiverThread; +// pthread_create(&receiverThread, NULL, receiver, &receiverParam); +// pthread_detach(receiverThread); + HostList::const_iterator it = remote_host_list.begin(); for(;it != remote_host_list.end(); it++) @@ -84,37 +77,37 @@ void* sender(void* p) void* receiver(void* p) { - ThreadParam* param = reinterpret_cast(p); +// SenderThreadParam* param = reinterpret_cast(p); - try - { - Buffer buf(u_int32_t(MAX_PACKET_SIZE)); - string remote_host; - u_int16_t remote_port; - - while(1) { - buf.setLength(MAX_PACKET_SIZE); - u_int32_t len = param->sock_.recvFrom(buf.getBuf(), buf.getLength(), remote_host, remote_port); - buf.setLength(len); - - if(remote_host != param->first_receiver_.addr_ || remote_port != param->first_receiver_.port_) - continue; +// try +// { +// Buffer buf(u_int32_t(MAX_PACKET_SIZE)); +// string remote_host; +// u_int16_t remote_port; + +// while(1) { +// buf.setLength(MAX_PACKET_SIZE); +// u_int32_t len = param->sock_.recvFrom(buf.getBuf(), buf.getLength(), remote_host, remote_port); +// buf.setLength(len); + +// if(remote_host != param->first_receiver_.addr_ || remote_port != param->first_receiver_.port_) +// continue; - Host control_host = param->control_.getHost(); - if(control_host.addr_ == "" || !control_host.port_) - { - cLog.msg(Log::PRIO_NOTICE) << "no control host detected till now, ignoring packet"; - continue; - } - - param->control_sock_.sendTo(buf.getBuf(), buf.getLength(), control_host.addr_, control_host.port_); - } - } - catch(std::exception &e) - { - cLog.msg(Log::PRIO_ERR) << "receiver exiting because: " << e.what() << std::endl; - } - pthread_exit(NULL); +// Host control_host = param->control_.getHost(); +// if(control_host.addr_ == "" || !control_host.port_) +// { +// cLog.msg(Log::PRIO_NOTICE) << "no control host detected till now, ignoring packet"; +// continue; +// } + +// param->control_sock_.sendTo(buf.getBuf(), buf.getLength(), control_host.addr_, control_host.port_); +// } +// } +// catch(std::exception &e) +// { +// cLog.msg(Log::PRIO_ERR) << "receiver exiting because: " << e.what() << std::endl; +// } +// pthread_exit(NULL); } void chrootAndDrop(string const& chrootdir, string const& username) @@ -190,28 +183,11 @@ int main(int argc, char* argv[]) SignalController sig; sig.init(); - try { - ControlHost control_host; - UDPSocket control_sock(gOpt.getControlInterface().addr_, gOpt.getControlInterface().port_); - UDPSocket sock(gOpt.getSendPort()); - - ThreadParam senderParam = {control_host, control_sock, sock, gOpt.getRemoteHosts().front()}; - pthread_t senderThread; - pthread_create(&senderThread, NULL, sender, &senderParam); - pthread_detach(senderThread); - - ThreadParam receiverParam = {control_host, control_sock, sock, gOpt.getRemoteHosts().front()}; - pthread_t receiverThread; - pthread_create(&receiverThread, NULL, receiver, &receiverParam); - pthread_detach(receiverThread); + pthread_t senderThread; + pthread_create(&senderThread, NULL, sender, NULL); + pthread_detach(senderThread); - int ret = sig.run(); - return ret; - } - catch(std::exception& e) - { - cLog.msg(Log::PRIO_ERR) << "an error occurred: " << e.what(); - return -1; - } + int ret = sig.run(); + return ret; } diff --git a/anytun.cpp b/anytun.cpp index 703e1cf..0a63a01 100644 --- a/anytun.cpp +++ b/anytun.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include // for ENOMEM @@ -43,7 +44,6 @@ #include "cipher.h" #include "keyDerivation.h" #include "authAlgo.h" -#include "authTag.h" #include "cipherFactory.h" #include "authAlgoFactory.h" #include "keyDerivationFactory.h" @@ -90,20 +90,6 @@ void createConnection(const std::string & remote_host, u_int16_t remote_port, Co queue.push(sc2); } - -void addPacketAuthTag(EncryptedPacket& pack, AuthAlgo* a, ConnectionParam& conn) -{ - AuthTag at = a->calc(pack); - pack.setAuthTag( at ); -} - -bool checkPacketAuthTag(EncryptedPacket& pack, AuthAlgo* a, ConnectionParam & conn) -{ - // check auth_tag and remove it - AuthTag at = pack.getAuthTag(); - return (at == a->calc(pack)); -} - bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn) { // compare sender_id and seq with window @@ -123,8 +109,8 @@ void* sender(void* p) ThreadParam* param = reinterpret_cast(p); std::auto_ptr c(CipherFactory::create(gOpt.getCipher())); -// std::auto_ptr a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) ); - + std::auto_ptr a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) ); + PlainPacket plain_packet(MAX_PACKET_LENGTH); EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH); @@ -161,7 +147,7 @@ void* sender(void* p) if(conn.remote_host_==""||!conn.remote_port_) continue; - // generate packet-key + // generate packet-key TODO: do this only when needed conn.kd_.generate(LABEL_SATP_ENCRYPTION, conn.seq_nr_, session_key); conn.kd_.generate(LABEL_SATP_SALT, conn.seq_nr_, session_salt); @@ -174,10 +160,13 @@ void* sender(void* p) encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux); conn.seq_nr_++; - // TODO: activate authentication -// conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key); -// a->setKey(session_auth_key); -// addPacketAuthTag(encrypted_packet, a.get(), conn); + // add authentication tag + if(a->getMaxLength()) { + encrypted_packet.addAuthTag(); + conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key); + a->setKey(session_auth_key); + a->generate(encrypted_packet); + } param->src.send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_host_, conn.remote_port_); } @@ -223,7 +212,7 @@ void* receiver(void* p) ThreadParam* param = reinterpret_cast(p); std::auto_ptr c( CipherFactory::create(gOpt.getCipher()) ); -// std::auto_ptr a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) ); + std::auto_ptr a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) ); EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH); PlainPacket plain_packet(MAX_PACKET_LENGTH); @@ -243,13 +232,7 @@ void* receiver(void* p) // read packet from socket u_int32_t len = param->src.recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_host, remote_port); encrypted_packet.setLength(len); - - // TODO: check auth tag first -// conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key); -// a->setKey( session_auth_key ); -// if(!checkPacketAuthTag(encrypted_packet, a.get(), conn)) -// continue; - + mux_t mux = encrypted_packet.getMux(); // autodetect peer if(gOpt.getRemoteAddr() == "" && param->cl.empty()) @@ -263,6 +246,17 @@ void* receiver(void* p) continue; ConnectionParam & conn = cit->second; + // check whether auth tag is ok or not + if(a->getMaxLength()) { + conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key); + a->setKey(session_auth_key); + if(!a->checkTag(encrypted_packet)) { + cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl; + continue; + } + encrypted_packet.removeAuthTag(); + } + //Allow dynamic IP changes //TODO: add command line option to turn this off if (remote_host != conn.remote_host_ || remote_port != conn.remote_port_) @@ -316,9 +310,15 @@ bool initLibGCrypt() std::cout << "initLibGCrypt: Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION << std::endl; return false; } + + gcry_error_t err = gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if( err ) { + std::cout << "initLibGCrypt: Failed to disable secure memory: " << gpg_strerror( err ) << std::endl; + return false; + } // Tell Libgcrypt that initialization has completed. - gcry_error_t err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); + err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); if( err ) { std::cout << "initLibGCrypt: Failed to finish the initialization of libgcrypt: " << gpg_strerror( err ) << std::endl; return false; @@ -327,6 +327,27 @@ bool initLibGCrypt() cLog.msg(Log::PRIO_NOTICE) << "initLibGCrypt: libgcrypt init finished"; return true; } + +void daemonize() +{ + pid_t pid; + + pid = fork(); + if(pid) exit(0); + setsid(); + pid = fork(); + if(pid) exit(0); + + std::cout << "running in background now..." << std::endl; + + int fd; + for (fd=getdtablesize();fd>=0;--fd) // close all file descriptors + close(fd); + fd=open("/dev/null",O_RDWR); // stdin + dup(fd); // stdout + dup(fd); // stderr + umask(027); +} int main(int argc, char* argv[]) { @@ -336,6 +357,9 @@ int main(int argc, char* argv[]) gOpt.printUsage(); exit(-1); } + if(gOpt.getDaemonize()) + daemonize(); + cLog.msg(Log::PRIO_NOTICE) << "anytun started..."; SignalController sig; diff --git a/authAlgo.cpp b/authAlgo.cpp index 3b1967e..6b1c9ec 100644 --- a/authAlgo.cpp +++ b/authAlgo.cpp @@ -31,24 +31,31 @@ #include "authAlgo.h" #include "log.h" #include "buffer.h" -#include "authTag.h" -#include "threadUtils.hpp" +#include "encryptedPacket.h" + +#include #include //****** NullAuthAlgo ****** +void NullAuthAlgo::generate(EncryptedPacket& packet) +{ +} -AuthTag NullAuthAlgo::calc(const Buffer& buf) +bool NullAuthAlgo::checkTag(EncryptedPacket& packet) { - return AuthTag(0); + return true; +} + +u_int32_t NullAuthAlgo::getMaxLength() +{ + return MAX_LENGTH_; } //****** Sha1AuthAlgo ****** Sha1AuthAlgo::Sha1AuthAlgo() : ctx_(NULL) { - Lock lock(mutex_); - gcry_error_t err = gcry_md_open( &ctx_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC ); if( err ) cLog.msg(Log::PRIO_CRIT) << "Sha1AuthAlgo::Sha1AuthAlgo: Failed to open message digest algo"; @@ -56,36 +63,63 @@ Sha1AuthAlgo::Sha1AuthAlgo() : ctx_(NULL) Sha1AuthAlgo::~Sha1AuthAlgo() { - Lock lock(mutex_); - - gcry_md_close( ctx_ ); - cLog.msg(Log::PRIO_DEBUG) << "Sha1AuthAlgo::~Sha1AuthAlgo: closed hmac handler"; + if(ctx_) + gcry_md_close( ctx_ ); } -void Sha1AuthAlgo::setKey(Buffer key) +void Sha1AuthAlgo::setKey(Buffer& key) { - Lock lock(mutex_); + if(!ctx_) + return; - gcry_error_t err; - err = gcry_md_setkey( ctx_, key.getBuf(), key.getLength() ); + gcry_error_t err = gcry_md_setkey( ctx_, key.getBuf(), key.getLength() ); if( err ) cLog.msg(Log::PRIO_ERR) << "Sha1AuthAlgo::setKey: Failed to set cipher key: " << gpg_strerror( err ); } -AuthTag Sha1AuthAlgo::calc(const Buffer& buf) +void Sha1AuthAlgo::generate(EncryptedPacket& packet) { - Lock lock(mutex_); + if(!packet.getAuthTagLength()) + return; - // gcry_error_t err; - AuthTag hmac(10); // 10byte - gcry_mpi_t tmp = gcry_mpi_new(160); // 20byte + gcry_md_reset( ctx_ ); - gcry_md_write( ctx_, static_cast(buf).getBuf(), buf.getLength() ); + gcry_md_write( ctx_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength() ); gcry_md_final( ctx_ ); - gcry_mpi_scan( &tmp, GCRYMPI_FMT_STD, gcry_md_read(ctx_, 0), 20, NULL ); - gcry_mpi_clear_highbit( tmp, 81 ); // truncate hmac from 20byte to 10byte - gcry_mpi_print( GCRYMPI_FMT_STD, hmac, hmac.getLength(), NULL, tmp ); - return hmac; + + u_int8_t* tag = packet.getAuthTag(); + if(packet.getAuthTagLength() > MAX_LENGTH_) + std::memset(tag, 0, (packet.getAuthTagLength() - MAX_LENGTH_)); + + u_int8_t* hmac = gcry_md_read(ctx_, 0); + u_int32_t length = (packet.getAuthTagLength() < MAX_LENGTH_) ? packet.getAuthTagLength() : MAX_LENGTH_; + std::memcpy(&tag[packet.getAuthTagLength() - length], &hmac[MAX_LENGTH_ - length], length); } +bool Sha1AuthAlgo::checkTag(EncryptedPacket& packet) +{ + if(!packet.getAuthTagLength()) + return true; + + gcry_md_reset( ctx_ ); + + gcry_md_write( ctx_, packet.getAuthenticatedPortion(), packet.getAuthenticatedPortionLength() ); + gcry_md_final( ctx_ ); + u_int8_t* tag = packet.getAuthTag(); + if(packet.getAuthTagLength() > MAX_LENGTH_) + for(u_int32_t i=0; i < (packet.getAuthTagLength() - MAX_LENGTH_); ++i) + if(tag[i]) return false; + + u_int8_t* hmac = gcry_md_read(ctx_, 0); + u_int32_t length = (packet.getAuthTagLength() < MAX_LENGTH_) ? packet.getAuthTagLength() : MAX_LENGTH_; + if(std::memcmp(&tag[packet.getAuthTagLength() - length], &hmac[MAX_LENGTH_ - length], length)) + return false; + + return true; +} + +u_int32_t Sha1AuthAlgo::getMaxLength() +{ + return MAX_LENGTH_; +} diff --git a/authAlgo.h b/authAlgo.h index bf72e32..b0832a5 100644 --- a/authAlgo.h +++ b/authAlgo.h @@ -31,10 +31,9 @@ #ifndef _AUTHALGO_H_ #define _AUTHALGO_H_ -#include "authTag.h" #include "datatypes.h" #include "buffer.h" -#include "threadUtils.hpp" +#include "encryptedPacket.h" #include @@ -48,14 +47,24 @@ public: * set the key for the auth algo * @param key key for hmac calculation */ - virtual void setKey(Buffer key) = 0; + virtual void setKey(Buffer& key) = 0; /** - * calculate the sha1 hmac - * @param buf buffer for message digest - * @return sha1 hmac + * generate the mac + * @param packet the packet to be authenticated */ - virtual AuthTag calc(const Buffer& buf) = 0; + virtual void generate(EncryptedPacket& packet) = 0; + + /** + * check the mac + * @param packet the packet to be authenticated + */ + virtual bool checkTag(EncryptedPacket& packet) = 0; + + /** + * get the maximum size of the auth algo + */ + virtual u_int32_t getMaxLength() = 0; }; //****** NullAuthAlgo ****** @@ -63,8 +72,12 @@ public: class NullAuthAlgo : public AuthAlgo { public: - AuthTag calc(const Buffer& buf); - void setKey(Buffer key) {}; + void setKey(Buffer& key) {}; + void generate(EncryptedPacket& packet); + bool checkTag(EncryptedPacket& packet); + u_int32_t getMaxLength(); + + static const u_int32_t MAX_LENGTH_ = 0; }; @@ -77,12 +90,15 @@ public: Sha1AuthAlgo(); ~Sha1AuthAlgo(); - void setKey(Buffer key); - AuthTag calc(const Buffer& buf); + void setKey(Buffer& key); + void generate(EncryptedPacket& packet); + bool checkTag(EncryptedPacket& packet); + u_int32_t getMaxLength(); + + static const u_int32_t MAX_LENGTH_ = 20; -protected: +private: gcry_md_hd_t ctx_; - Mutex mutex_; }; #endif diff --git a/authTag.cpp b/authTag.cpp deleted file mode 100644 index fe5dc6d..0000000 --- a/authTag.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * anytun - * - * The secure anycast tunneling protocol (satp) defines a protocol used - * for communication between any combination of unicast and anycast - * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel - * mode and allows tunneling of every ETHER TYPE protocol (e.g. - * ethernet, ip, arp ...). satp directly includes cryptography and - * message authentication based on the methodes used by SRTP. It is - * intended to deliver a generic, scaleable and secure solution for - * tunneling and relaying of packets of any protocol. - * - * - * Copyright (C) 2007 anytun.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include "datatypes.h" -#include "authTag.h" - -AuthTag::AuthTag() -{ -} - -AuthTag::AuthTag(u_int32_t length) : Buffer(length) -{ -} - -AuthTag::AuthTag(const Buffer &src) : Buffer(src) -{ -} - -AuthTag::AuthTag(u_int8_t* data, u_int32_t length) : Buffer(data, length) -{ -} diff --git a/authTag.h b/authTag.h deleted file mode 100644 index 22237e6..0000000 --- a/authTag.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * anytun - * - * The secure anycast tunneling protocol (satp) defines a protocol used - * for communication between any combination of unicast and anycast - * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel - * mode and allows tunneling of every ETHER TYPE protocol (e.g. - * ethernet, ip, arp ...). satp directly includes cryptography and - * message authentication based on the methodes used by SRTP. It is - * intended to deliver a generic, scaleable and secure solution for - * tunneling and relaying of packets of any protocol. - * - * - * Copyright (C) 2007 anytun.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _AUTHTAG_H_ -#define _AUTHTAG_H_ - -#include "datatypes.h" -#include "buffer.h" - - -/** - * Authtag class - */ - -class AuthTag : public Buffer -{ -public: - AuthTag(); - AuthTag(u_int32_t length); - AuthTag(const Buffer &src); - AuthTag(u_int8_t* data, u_int32_t length); - -private: - -}; - -#endif diff --git a/buffer.cpp b/buffer.cpp index 675383b..250a806 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -56,6 +56,12 @@ Buffer::Buffer(u_int32_t length, bool allow_realloc) : length_(length), real_len Buffer::Buffer(u_int8_t* data, u_int32_t length, bool allow_realloc) : length_(length), real_length_(length + Buffer::OVER_SIZE_), allow_realloc_(allow_realloc) { + if(!data) { + length_ = 0; + real_length_ = 0; + return; + } + buf_ = new u_int8_t[real_length_]; if(!buf_) { length_ = 0; @@ -182,11 +188,11 @@ void Buffer::setLength(u_int32_t new_length) old_buf = &buf_[old_length]; std::memset(old_buf, 0, real_length_ - old_length); - - reinit(); } else length_ = new_length; + + reinit(); } diff --git a/cipher.cpp b/cipher.cpp index 3a7344e..5103480 100644 --- a/cipher.cpp +++ b/cipher.cpp @@ -73,7 +73,7 @@ u_int32_t NullCipher::decipher(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_in //****** AesIcmCipher ****** -AesIcmCipher::AesIcmCipher() +AesIcmCipher::AesIcmCipher() : cipher_(NULL) { // TODO: hardcoded keysize gcry_error_t err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 ); @@ -84,20 +84,21 @@ AesIcmCipher::AesIcmCipher() AesIcmCipher::~AesIcmCipher() { - gcry_cipher_close( cipher_ ); + if(cipher_) + gcry_cipher_close( cipher_ ); } - -void AesIcmCipher::setKey(Buffer key) +void AesIcmCipher::setKey(Buffer& key) { - gcry_error_t err; + if(!cipher_) + return; - err = gcry_cipher_setkey( cipher_, key.getBuf(), key.getLength() ); + gcry_error_t err = gcry_cipher_setkey( cipher_, key.getBuf(), key.getLength() ); if( err ) cLog.msg(Log::PRIO_ERR) << "AesIcmCipher::setKey: Failed to set cipher key: " << gpg_strerror( err ); } -void AesIcmCipher::setSalt(Buffer salt) +void AesIcmCipher::setSalt(Buffer& salt) { salt_ = salt; if(!salt_[u_int32_t(0)]) @@ -118,6 +119,9 @@ u_int32_t AesIcmCipher::decipher(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_ void AesIcmCipher::calc(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id) { + if(!cipher_) + return; + gcry_error_t err = gcry_cipher_reset( cipher_ ); if( err ) { cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to reset cipher: " << gpg_strerror( err ); diff --git a/cipher.h b/cipher.h index 0749859..f899966 100644 --- a/cipher.h +++ b/cipher.h @@ -48,8 +48,8 @@ public: void encrypt(PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id); void decrypt(EncryptedPacket & in, PlainPacket & out); - virtual void setKey(Buffer key) = 0; - virtual void setSalt(Buffer salt) = 0; + virtual void setKey(Buffer& key) = 0; + virtual void setSalt(Buffer& salt) = 0; protected: virtual u_int32_t cipher(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id) = 0; @@ -61,8 +61,8 @@ protected: class NullCipher : public Cipher { public: - void setKey(Buffer key) {}; - void setSalt(Buffer salt) {}; + void setKey(Buffer& key) {}; + void setSalt(Buffer& salt) {}; protected: u_int32_t cipher(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id); @@ -76,8 +76,8 @@ class AesIcmCipher : public Cipher public: AesIcmCipher(); ~AesIcmCipher(); - void setKey(Buffer key); - void setSalt(Buffer salt); + void setKey(Buffer& key); + void setSalt(Buffer& salt); protected: u_int32_t cipher(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id); diff --git a/encryptedPacket.cpp b/encryptedPacket.cpp index b618f99..c0221e9 100644 --- a/encryptedPacket.cpp +++ b/encryptedPacket.cpp @@ -35,16 +35,14 @@ #include "encryptedPacket.h" #include "datatypes.h" -#include "authTag.h" #include "log.h" -// TODO: fix auth_tag stuff EncryptedPacket::EncryptedPacket(u_int32_t payload_length, bool allow_realloc) : Buffer(payload_length + sizeof(struct HeaderStruct), allow_realloc) { header_ = reinterpret_cast(buf_); - payload_ = buf_ + sizeof(struct HeaderStruct); // TODO: fix auth_tag stuff - auth_tag_ = NULL; // TODO: fix auth_tag stuff + payload_ = buf_ + sizeof(struct HeaderStruct); + auth_tag_ = NULL; if(header_) { header_->seq_nr = 0; @@ -107,7 +105,13 @@ void EncryptedPacket::setHeader(seq_nr_t seq_nr, sender_id_t sender_id, mux_t mu u_int32_t EncryptedPacket::getPayloadLength() const { - return (length_ > sizeof(struct HeaderStruct)) ? (length_ - sizeof(struct HeaderStruct)) : 0; // TODO: fix auth_tag stuff + if(!payload_) + return 0; + + if(!auth_tag_) + return (length_ > sizeof(struct HeaderStruct)) ? (length_ - sizeof(struct HeaderStruct)) : 0; + + return (length_ > (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) ? (length_ - sizeof(struct HeaderStruct) - AUTHTAG_SIZE) : 0; } void EncryptedPacket::setPayloadLength(u_int32_t payload_length) @@ -119,10 +123,25 @@ void EncryptedPacket::setPayloadLength(u_int32_t payload_length) void EncryptedPacket::reinit() { - Buffer::reinit(); header_ = reinterpret_cast(buf_); - payload_ = buf_ + sizeof(struct HeaderStruct); // TODO: fix auth_tag stuff - auth_tag_ = NULL; // TODO: fix auth_tag stuff + payload_ = buf_ + sizeof(struct HeaderStruct); + + if(length_ <= (sizeof(struct HeaderStruct))) + payload_ = NULL; + + if(length_ < (sizeof(struct HeaderStruct))) { + header_ = NULL; + throw std::runtime_error("packet can't be initialized, buffer is too small"); + } + + if(auth_tag_) + { + if(length_ < (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) { + auth_tag_ = NULL; + throw std::runtime_error("auth-tag can't be enabled, buffer is too small"); + } + auth_tag_ = buf_ + length_ - AUTHTAG_SIZE; + } } u_int8_t* EncryptedPacket::getPayload() @@ -130,62 +149,67 @@ u_int8_t* EncryptedPacket::getPayload() return payload_; } +u_int8_t* EncryptedPacket::getAuthenticatedPortion() +{ + return buf_; +} +u_int32_t EncryptedPacket::getAuthenticatedPortionLength() +{ + if(!buf_) + return 0; + if(!auth_tag_) + return length_; + + return (length_ > AUTHTAG_SIZE) ? (length_ - AUTHTAG_SIZE) : 0; +} - - -// TODO: fix auth_tag stuff - -bool EncryptedPacket::hasAuthTag() const +void EncryptedPacket::withAuthTag(bool b) { -// if( auth_tag_ == NULL ) - return false; -// return true; + if((b && auth_tag_) || (!b && !auth_tag_)) + return; + + if(b) + { + if(length_ < (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) + throw std::runtime_error("auth-tag can't be enabled, buffer is too small"); + + auth_tag_ = buf_ + length_ - AUTHTAG_SIZE; + } + else + auth_tag_ = NULL; } -void EncryptedPacket::withAuthTag(bool b) +void EncryptedPacket::addAuthTag() { -// if( b && (auth_tag_ != NULL) ) -// throw std::runtime_error("packet already has auth tag function enabled"); -// //TODO: return instead? -// if( ! b && (auth_tag_ == NULL) ) -// throw std::runtime_error("packet already has auth tag function disabled"); -// //TODO: return instead? + if(auth_tag_) + return; -// if( b ) { -// auth_tag_ = reinterpret_cast( buf_ + sizeof(struct HeaderStruct) ); -// payload_ = payload_ + AUTHTAG_SIZE; -// length_ -= AUTHTAG_SIZE; -// max_length_ -= AUTHTAG_SIZE; -// } else { -// payload_ = reinterpret_cast( auth_tag_ ); -// length_ += AUTHTAG_SIZE; -// max_length_ += AUTHTAG_SIZE; -// auth_tag_ = NULL; -// } + auth_tag_ = buf_; // will be set to the correct value @ reinit + setLength(length_ + AUTHTAG_SIZE); + if(auth_tag_ == buf_) // reinit was not called by setLength + reinit(); } -void EncryptedPacket::setAuthTag(AuthTag& tag) +void EncryptedPacket::removeAuthTag() { -// if( auth_tag_ == NULL ) -// throw std::runtime_error("auth tag not enabled"); - -// if( tag == AuthTag(0) ) -// return; + if(!auth_tag_) + return; -// if( tag.getLength() != AUTHTAG_SIZE ) -// throw std::length_error("authtag length mismatch with AUTHTAG_SIZE"); + auth_tag_ = NULL; + setLength(length_ - AUTHTAG_SIZE); +} -// std::memcpy( auth_tag_, tag.getBuf(), AUTHTAG_SIZE ); +u_int8_t* EncryptedPacket::getAuthTag() +{ + return auth_tag_; } -AuthTag EncryptedPacket::getAuthTag() const +u_int32_t EncryptedPacket::getAuthTagLength() { -// if( auth_tag_ == NULL ) -// throw std::runtime_error("auth tag not enabled"); + if(auth_tag_) + return AUTHTAG_SIZE; - AuthTag at(AUTHTAG_SIZE); -// std::memcpy(at, auth_tag_, AUTHTAG_SIZE ); - return at; + return 0; } diff --git a/encryptedPacket.h b/encryptedPacket.h index bb143f9..fc6fe96 100644 --- a/encryptedPacket.h +++ b/encryptedPacket.h @@ -33,7 +33,7 @@ #include "datatypes.h" #include "buffer.h" -#include "authTag.h" + class Cipher; class EncryptedPacket : public Buffer { @@ -114,12 +114,14 @@ public: u_int8_t* getPayload(); + u_int8_t* getAuthenticatedPortion(); + u_int32_t getAuthenticatedPortionLength(); - bool hasAuthTag() const; void withAuthTag(bool b); - AuthTag getAuthTag() const; - void setAuthTag(AuthTag& tag); - + void addAuthTag(); + void removeAuthTag(); + u_int8_t* getAuthTag(); + u_int32_t getAuthTagLength(); private: EncryptedPacket(); @@ -136,7 +138,7 @@ private: struct HeaderStruct* header_; u_int8_t * payload_; - AuthTag* auth_tag_; + u_int8_t * auth_tag_; static const u_int32_t AUTHTAG_SIZE = 10; // TODO: hardcoded size }; diff --git a/options.cpp b/options.cpp index 2a2b144..8e6040c 100644 --- a/options.cpp +++ b/options.cpp @@ -53,6 +53,7 @@ Options& Options::instance() Options::Options() : key_(u_int32_t(0)), salt_(u_int32_t(0)) { progname_ = "anytun"; + daemonize_ = true; sender_id_ = 0; local_addr_ = ""; local_port_ = 4444; @@ -150,6 +151,7 @@ bool Options::parse(int argc, char* argv[]) if(str == "-h" || str == "--help") return false; + PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", daemonize_) PARSE_SCALAR_PARAM("-s","--sender-id", sender_id_) PARSE_SCALAR_PARAM("-i","--interface", local_addr_) PARSE_SCALAR_PARAM("-p","--port", local_port_) @@ -174,9 +176,9 @@ bool Options::parse(int argc, char* argv[]) return false; } - if(cipher_ == "null") + if(cipher_ == "null" && auth_algo_ == "null") kd_prf_ = "null"; - if(cipher_ != "null" && kd_prf_ == "null") + if((cipher_ != "null" || auth_algo_ != "null") && kd_prf_ == "null") kd_prf_ = "aes-ctr"; while(!host_port_queue.empty()) @@ -198,6 +200,7 @@ void Options::printUsage() std::cout << "USAGE:" << std::endl; std::cout << "anytun [-h|--help] prints this..." << std::endl; // std::cout << " [-f|--config] the config file" << std::endl; + std::cout << " [-D|--nodaemonize] don't run in background" << std::endl; std::cout << " [-s|--sender-id ] the sender id to use" << std::endl; std::cout << " [-i|--interface] local anycast ip address to bind to" << std::endl; std::cout << " [-p|--port] local anycast(data) port to bind to" << std::endl; @@ -224,6 +227,7 @@ void Options::printOptions() { Lock lock(mutex); std::cout << "Options:" << std::endl; + std::cout << "daemonize=" << daemonize_ << std::endl; std::cout << "sender_id='" << sender_id_ << "'" << std::endl; std::cout << "local_addr='" << local_addr_ << "'" << std::endl; std::cout << "local_port='" << local_port_ << "'" << std::endl; @@ -258,6 +262,17 @@ Options& Options::setProgname(std::string p) return *this; } +bool Options::getDaemonize() +{ + return daemonize_; +} + +Options& Options::setDaemonize(bool d) +{ + daemonize_ = d; + return *this; +} + ConnectToList Options::getConnectTo() { Lock lock(mutex); diff --git a/options.h b/options.h index b34e012..0d7748a 100644 --- a/options.h +++ b/options.h @@ -55,6 +55,8 @@ public: std::string getProgname(); Options& setProgname(std::string p); + bool getDaemonize(); + Options& setDaemonize(bool d); sender_id_t getSenderId(); Options& setSenderId(sender_id_t s); std::string getLocalAddr(); @@ -118,6 +120,7 @@ private: ConnectToList connect_to_; std::string progname_; + bool daemonize_; sender_id_t sender_id_; std::string local_addr_; std::string local_sync_addr_; diff --git a/plainPacket.cpp b/plainPacket.cpp index f9c43ae..c1fd99a 100644 --- a/plainPacket.cpp +++ b/plainPacket.cpp @@ -61,6 +61,9 @@ void PlainPacket::setPayloadType(payload_type_t payload_type) u_int32_t PlainPacket::getPayloadLength() const { + if(!payload_) + return 0; + return (length_ > sizeof(payload_type_t)) ? (length_ - sizeof(payload_type_t)) : 0; } @@ -73,9 +76,17 @@ void PlainPacket::setPayloadLength(u_int32_t payload_length) void PlainPacket::reinit() { - Buffer::reinit(); payload_type_ = reinterpret_cast(buf_); payload_ = buf_ + sizeof(payload_type_t); + + if(length_ <= (sizeof(payload_type_t))) + payload_ = NULL; + + if(length_ < (sizeof(payload_type_t))) { + payload_type_ = NULL; + throw std::runtime_error("packet can't be initialized, buffer is too small"); + } + } u_int8_t* PlainPacket::getPayload() @@ -83,7 +94,6 @@ u_int8_t* PlainPacket::getPayload() return payload_; } - NetworkAddress PlainPacket::getSrcAddr() const { if(!payload_type_ || !payload_) @@ -108,12 +118,11 @@ NetworkAddress PlainPacket::getSrcAddr() const if(length_ < (sizeof(payload_type_t)+sizeof(struct ip6_hdr))) return NetworkAddress(); struct ip6_hdr* hdr = reinterpret_cast(payload_); - return NetworkAddress(hdr->ip6_dst); + return NetworkAddress(hdr->ip6_src); } return NetworkAddress(); } - NetworkAddress PlainPacket::getDstAddr() const { if(!payload_type_ || !payload_) -- cgit v1.2.3