summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--anyrtpproxy/anyrtpproxy.cpp140
-rw-r--r--anytun.cpp86
-rw-r--r--authAlgo.cpp82
-rw-r--r--authAlgo.h42
-rw-r--r--authTag.cpp49
-rw-r--r--authTag.h54
-rw-r--r--buffer.cpp10
-rw-r--r--cipher.cpp18
-rw-r--r--cipher.h12
-rw-r--r--encryptedPacket.cpp122
-rw-r--r--encryptedPacket.h14
-rw-r--r--options.cpp19
-rw-r--r--options.h3
-rw-r--r--plainPacket.cpp17
15 files changed, 339 insertions, 333 deletions
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 <list>
+#include <map>
+
#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<ThreadParam*>(p);
+private:
+ Mutex mutex;
+
+ std::map<ControlHost, std::pair<UDPSocket*, pthread_t>> 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<ThreadParam*>(p);
+// SenderThreadParam* param = reinterpret_cast<SenderThreadParam*>(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 <iostream>
#include <poll.h>
+#include <fcntl.h>
#include <gcrypt.h>
#include <cerrno> // 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<ThreadParam*>(p);
std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher()));
-// std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
-
+ std::auto_ptr<AuthAlgo> 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<ThreadParam*>(p);
std::auto_ptr<Cipher> c( CipherFactory::create(gOpt.getCipher()) );
-// std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
+ std::auto_ptr<AuthAlgo> 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 <iostream>
#include <gcrypt.h>
//****** 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<Buffer>(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 <gcrypt.h>
@@ -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 <satp@wirdorange.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 <stdexcept>
-#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 <satp@wirdorange.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<struct HeaderStruct*>(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<struct HeaderStruct*>(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<AuthTag*>( buf_ + sizeof(struct HeaderStruct) );
-// payload_ = payload_ + AUTHTAG_SIZE;
-// length_ -= AUTHTAG_SIZE;
-// max_length_ -= AUTHTAG_SIZE;
-// } else {
-// payload_ = reinterpret_cast<u_int8_t*>( 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] <file> the config file" << std::endl;
+ std::cout << " [-D|--nodaemonize] don't run in background" << std::endl;
std::cout << " [-s|--sender-id ] <sender id> the sender id to use" << std::endl;
std::cout << " [-i|--interface] <ip-address> local anycast ip address to bind to" << std::endl;
std::cout << " [-p|--port] <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<payload_type_t*>(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<struct ip6_hdr*>(payload_);
- return NetworkAddress(hdr->ip6_dst);
+ return NetworkAddress(hdr->ip6_src);
}
return NetworkAddress();
}
-
NetworkAddress PlainPacket::getDstAddr() const
{
if(!payload_type_ || !payload_)