2014-08-25 09:02:40 +02:00
|
|
|
// OpenVPN -- An application to securely tunnel IP networks
|
|
|
|
// over a single port, with support for SSL/TLS-based
|
|
|
|
// session authentication and key exchange,
|
|
|
|
// packet encryption, packet authentication, and
|
|
|
|
// packet compression.
|
2013-01-31 16:00:45 +01:00
|
|
|
//
|
2014-08-25 09:02:40 +02:00
|
|
|
// Copyright (C) 2013-2014 OpenVPN Technologies, Inc.
|
2013-01-31 16:00:45 +01:00
|
|
|
//
|
2014-08-25 09:02:40 +02:00
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License Version 3
|
|
|
|
// as published by the Free Software Foundation.
|
2013-01-31 16:00:45 +01:00
|
|
|
//
|
2014-08-25 09:02:40 +02:00
|
|
|
// 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 Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program in the COPYING file.
|
|
|
|
// If not, see <http://www.gnu.org/licenses/>.
|
2013-01-31 16:00:45 +01:00
|
|
|
|
2013-01-30 17:24:37 +01:00
|
|
|
// Unit test for OpenVPN Protocol implementation (class ProtoContext)
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
#include <sstream>
|
|
|
|
#include <deque>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cstring>
|
|
|
|
#include <limits>
|
|
|
|
|
2014-03-04 02:43:13 +01:00
|
|
|
#include <openvpn/common/platform.hpp>
|
|
|
|
|
|
|
|
#ifdef OPENVPN_PLATFORM_WIN
|
|
|
|
#include "protowin.h"
|
|
|
|
#endif
|
|
|
|
|
2011-12-14 12:34:33 +01:00
|
|
|
#define OPENVPN_DEBUG
|
2012-03-12 13:24:40 +01:00
|
|
|
#define OPENVPN_ENABLE_ASSERT
|
2011-12-13 05:46:56 +01:00
|
|
|
#define USE_TLS_AUTH
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2012-03-11 13:09:25 +01:00
|
|
|
#define OPENVPN_LOG_SSL(x) // disable
|
|
|
|
|
2014-03-03 22:43:38 +01:00
|
|
|
// how many virtual seconds between SSL renegotiations
|
|
|
|
#ifndef RENEG
|
2014-03-05 01:42:00 +01:00
|
|
|
#define RENEG 900
|
2014-03-03 22:43:38 +01:00
|
|
|
#endif
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// number of threads to use for test
|
2011-12-13 05:46:56 +01:00
|
|
|
#ifndef N_THREADS
|
|
|
|
#define N_THREADS 1
|
|
|
|
#endif
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// number of iterations
|
2011-12-13 05:46:56 +01:00
|
|
|
#ifndef ITER
|
|
|
|
#define ITER 1000000
|
|
|
|
#endif
|
|
|
|
|
2011-12-17 11:53:21 +01:00
|
|
|
// number of high-level session iterations
|
|
|
|
#ifndef SITER
|
|
|
|
#define SITER 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// abort if we reach this limit
|
|
|
|
//#define DROUGHT_LIMIT 100000
|
|
|
|
|
2012-02-07 13:56:32 +01:00
|
|
|
#if !defined(VERBOSE) && !defined(QUIET) && ITER <= 10000
|
2011-12-13 05:46:56 +01:00
|
|
|
#define VERBOSE
|
|
|
|
#endif
|
|
|
|
|
2012-09-15 08:56:18 +02:00
|
|
|
#ifdef VERBOSE
|
2013-01-30 17:24:37 +01:00
|
|
|
#define OPENVPN_DEBUG_PROTO 1
|
2012-09-15 08:56:18 +02:00
|
|
|
#endif
|
|
|
|
|
2012-03-26 00:07:45 +02:00
|
|
|
#define STRINGIZE1(x) #x
|
|
|
|
#define STRINGIZE(x) STRINGIZE1(x)
|
|
|
|
|
|
|
|
// setup cipher
|
|
|
|
#ifndef PROTO_CIPHER
|
|
|
|
#define PROTO_CIPHER AES-128-CBC
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// setup digest
|
|
|
|
#ifndef PROTO_DIGEST
|
|
|
|
#define PROTO_DIGEST SHA1
|
2012-03-23 21:04:33 +01:00
|
|
|
#endif
|
|
|
|
|
2012-02-11 15:02:51 +01:00
|
|
|
#include <openvpn/log/logsimple.hpp>
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
#include <openvpn/common/thread.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#include <openvpn/common/exception.hpp>
|
|
|
|
#include <openvpn/common/file.hpp>
|
|
|
|
#include <openvpn/time/time.hpp>
|
2013-05-22 07:13:11 +02:00
|
|
|
#include <openvpn/random/randint.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#include <openvpn/frame/frame.hpp>
|
|
|
|
#include <openvpn/ssl/proto.hpp>
|
2012-03-12 13:24:40 +01:00
|
|
|
#include <openvpn/init/initprocess.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2014-10-17 23:52:29 +02:00
|
|
|
#include <openvpn/crypto/cryptodcsel.hpp>
|
2014-10-08 21:43:40 +02:00
|
|
|
|
2014-03-05 01:42:00 +01:00
|
|
|
#if !(defined(USE_OPENSSL) || defined(USE_POLARSSL) || defined(USE_APPLE_SSL))
|
|
|
|
#error Must define one or more of USE_OPENSSL, USE_POLARSSL, USE_APPLE_SSL.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(USE_OPENSSL) && (defined(USE_POLARSSL) || defined(USE_APPLE_SSL))
|
|
|
|
#undef USE_OPENSSL
|
|
|
|
#define USE_OPENSSL_SERVER
|
|
|
|
#elif !defined(USE_OPENSSL) && defined(USE_POLARSSL)
|
|
|
|
#define USE_POLARSSL_SERVER
|
|
|
|
#elif defined(USE_OPENSSL) && !defined(USE_POLARSSL)
|
|
|
|
#define USE_OPENSSL_SERVER
|
|
|
|
#else
|
|
|
|
#error no server setup
|
|
|
|
#endif
|
|
|
|
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(USE_OPENSSL) || defined(USE_OPENSSL_SERVER)
|
2012-03-13 05:51:52 +01:00
|
|
|
#include <openvpn/openssl/util/init.hpp>
|
|
|
|
|
2012-03-12 13:24:40 +01:00
|
|
|
#include <openvpn/openssl/crypto/api.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#include <openvpn/openssl/ssl/sslctx.hpp>
|
2012-03-11 13:09:25 +01:00
|
|
|
#include <openvpn/openssl/util/rand.hpp>
|
2011-12-13 05:46:56 +01:00
|
|
|
|
2012-03-14 01:51:40 +01:00
|
|
|
// kludge to work around symbol conflict between OpenSSL and PolarSSL
|
|
|
|
#undef KU_DIGITAL_SIGNATURE
|
|
|
|
#undef KU_NON_REPUDIATION
|
|
|
|
#undef KU_KEY_ENCIPHERMENT
|
|
|
|
#undef KU_DATA_ENCIPHERMENT
|
|
|
|
#undef KU_KEY_AGREEMENT
|
|
|
|
#undef KU_KEY_CERT_SIGN
|
|
|
|
#undef KU_CRL_SIGN
|
|
|
|
#undef SSL_VERIFY_NONE
|
2012-09-15 08:56:18 +02:00
|
|
|
#endif
|
2012-03-14 01:51:40 +01:00
|
|
|
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(USE_APPLE_SSL)
|
2012-03-13 05:51:52 +01:00
|
|
|
#include <openvpn/applecrypto/crypto/api.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#include <openvpn/applecrypto/ssl/sslctx.hpp>
|
2012-03-11 13:09:25 +01:00
|
|
|
#include <openvpn/applecrypto/util/rand.hpp>
|
|
|
|
#endif
|
|
|
|
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(USE_POLARSSL) || defined(USE_POLARSSL_SERVER)
|
2012-03-13 05:51:52 +01:00
|
|
|
#include <openvpn/polarssl/crypto/api.hpp>
|
2012-03-14 01:51:40 +01:00
|
|
|
#include <openvpn/polarssl/ssl/sslctx.hpp>
|
2012-03-11 13:09:25 +01:00
|
|
|
#include <openvpn/polarssl/util/rand.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
#if OPENVPN_MULTITHREAD
|
|
|
|
#include <boost/bind.hpp>
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
|
|
|
|
2014-03-04 18:42:07 +01:00
|
|
|
#include <openvpn/crypto/selftest.hpp>
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
using namespace openvpn;
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2014-03-05 01:42:00 +01:00
|
|
|
// server Crypto/SSL/Rand implementation
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(USE_POLARSSL_SERVER)
|
|
|
|
typedef PolarSSLCryptoAPI ServerCryptoAPI;
|
2014-10-15 20:53:18 +02:00
|
|
|
typedef PolarSSLContext ServerSSLAPI;
|
2012-09-15 08:56:18 +02:00
|
|
|
typedef PolarSSLRandom ServerRandomAPI;
|
2014-03-05 01:42:00 +01:00
|
|
|
#elif defined(USE_OPENSSL_SERVER)
|
2012-03-12 13:24:40 +01:00
|
|
|
typedef OpenSSLCryptoAPI ServerCryptoAPI;
|
|
|
|
typedef OpenSSLContext ServerSSLAPI;
|
|
|
|
typedef OpenSSLRandom ServerRandomAPI;
|
2014-03-05 01:42:00 +01:00
|
|
|
#else
|
|
|
|
#error No server SSL implementation defined
|
2012-09-15 08:56:18 +02:00
|
|
|
#endif
|
2011-12-18 11:50:08 +01:00
|
|
|
|
2012-03-11 13:09:25 +01:00
|
|
|
// client SSL implementation can be OpenSSL, Apple SSL, or PolarSSL
|
2012-03-13 05:51:52 +01:00
|
|
|
#if defined(USE_POLARSSL)
|
|
|
|
typedef PolarSSLCryptoAPI ClientCryptoAPI;
|
2014-10-15 20:53:18 +02:00
|
|
|
typedef PolarSSLContext ClientSSLAPI;
|
2012-03-13 05:51:52 +01:00
|
|
|
typedef PolarSSLRandom ClientRandomAPI;
|
2012-03-11 13:09:25 +01:00
|
|
|
#elif defined(USE_APPLE_SSL)
|
2012-03-15 13:13:16 +01:00
|
|
|
typedef AppleCryptoAPI ClientCryptoAPI;
|
2012-03-12 13:24:40 +01:00
|
|
|
typedef AppleSSLContext ClientSSLAPI;
|
|
|
|
typedef AppleRandom ClientRandomAPI;
|
2012-03-13 05:51:52 +01:00
|
|
|
#elif defined(USE_OPENSSL)
|
|
|
|
typedef OpenSSLCryptoAPI ClientCryptoAPI;
|
|
|
|
typedef OpenSSLContext ClientSSLAPI;
|
|
|
|
typedef OpenSSLRandom ClientRandomAPI;
|
2011-12-18 11:50:08 +01:00
|
|
|
#else
|
2012-03-11 13:09:25 +01:00
|
|
|
#error No client SSL implementation defined
|
2011-12-18 11:50:08 +01:00
|
|
|
#endif
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
const char message[] =
|
|
|
|
"Message _->_ 0000000000 It was a bright cold day in April, and the clocks\n"
|
|
|
|
"were striking thirteen. Winston Smith, his chin nuzzled\n"
|
|
|
|
"into his breast in an effort to escape the vile wind,\n"
|
|
|
|
"slipped quickly through the glass doors of Victory\n"
|
|
|
|
"Mansions, though not quickly enough to prevent a\n"
|
|
|
|
"swirl of gritty dust from entering along with him.\n"
|
|
|
|
#ifdef LARGE_MESSAGE
|
|
|
|
"It was a bright cold day in April, and the clocks\n"
|
|
|
|
"were striking thirteen. Winston Smith, his chin nuzzled\n"
|
|
|
|
"into his breast in an effort to escape the vile wind,\n"
|
|
|
|
"slipped quickly through the glass doors of Victory\n"
|
|
|
|
"Mansions, though not quickly enough to prevent a\n"
|
|
|
|
"swirl of gritty dust from entering along with him.\n"
|
|
|
|
"It was a bright cold day in April, and the clocks\n"
|
|
|
|
"were striking thirteen. Winston Smith, his chin nuzzled\n"
|
|
|
|
"into his breast in an effort to escape the vile wind,\n"
|
|
|
|
"slipped quickly through the glass doors of Victory\n"
|
|
|
|
"Mansions, though not quickly enough to prevent a\n"
|
|
|
|
"swirl of gritty dust from entering along with him.\n"
|
|
|
|
"It was a bright cold day in April, and the clocks\n"
|
|
|
|
"were striking thirteen. Winston Smith, his chin nuzzled\n"
|
|
|
|
"into his breast in an effort to escape the vile wind,\n"
|
|
|
|
"slipped quickly through the glass doors of Victory\n"
|
|
|
|
"Mansions, though not quickly enough to prevent a\n"
|
|
|
|
"swirl of gritty dust from entering along with him.\n"
|
|
|
|
"It was a bright cold day in April, and the clocks\n"
|
|
|
|
"were striking thirteen. Winston Smith, his chin nuzzled\n"
|
|
|
|
"into his breast in an effort to escape the vile wind,\n"
|
|
|
|
"slipped quickly through the glass doors of Victory\n"
|
|
|
|
"Mansions, though not quickly enough to prevent a\n"
|
|
|
|
"swirl of gritty dust from entering along with him.\n"
|
|
|
|
#endif
|
|
|
|
;
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// A "Drought" measures the maximum period of time between
|
|
|
|
// any two successive events. Used to measure worst-case
|
|
|
|
// packet loss.
|
2011-12-13 05:46:56 +01:00
|
|
|
class DroughtMeasure
|
|
|
|
{
|
|
|
|
public:
|
2011-12-17 11:53:21 +01:00
|
|
|
OPENVPN_SIMPLE_EXCEPTION(drought_limit_exceeded);
|
|
|
|
|
|
|
|
DroughtMeasure(const std::string& name_arg, TimePtr now_arg)
|
|
|
|
: now(now_arg), name(name_arg)
|
2011-12-13 05:46:56 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void event()
|
|
|
|
{
|
|
|
|
if (last_event.defined())
|
|
|
|
{
|
|
|
|
Time::Duration since_last = *now - last_event;
|
|
|
|
if (since_last > drought)
|
2011-12-17 11:53:21 +01:00
|
|
|
{
|
|
|
|
drought = since_last;
|
|
|
|
#if defined(VERBOSE) || defined(DROUGHT_LIMIT)
|
|
|
|
{
|
|
|
|
const unsigned int r = drought.raw();
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << "*** Drought " << name << " has reached " << r << std::endl;
|
|
|
|
#endif
|
|
|
|
#ifdef DROUGHT_LIMIT
|
|
|
|
if (r > DROUGHT_LIMIT)
|
|
|
|
throw drought_limit_exceeded();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2011-12-13 05:46:56 +01:00
|
|
|
}
|
|
|
|
last_event = *now;
|
|
|
|
}
|
|
|
|
|
|
|
|
Time::Duration operator()() const { return drought; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
TimePtr now;
|
|
|
|
Time last_event;
|
|
|
|
Time::Duration drought;
|
2011-12-17 11:53:21 +01:00
|
|
|
std::string name;
|
2011-12-13 05:46:56 +01:00
|
|
|
};
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// test the OpenVPN protocol implementation in ProtoContext
|
2014-10-16 02:12:38 +02:00
|
|
|
template <typename CRYPTO_API>
|
|
|
|
class TestProto : public ProtoContext<CRYPTO_API>
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
2014-10-16 02:12:38 +02:00
|
|
|
typedef ProtoContext<CRYPTO_API> Base;
|
2011-12-11 09:28:55 +01:00
|
|
|
|
|
|
|
using Base::now;
|
2011-12-18 11:50:08 +01:00
|
|
|
using Base::mode;
|
|
|
|
using Base::is_server;
|
2011-12-11 09:28:55 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
using Base::flush;
|
|
|
|
|
|
|
|
typedef typename Base::PacketType PacketType;
|
|
|
|
|
|
|
|
TestProto(const typename Base::Config::Ptr& config,
|
2012-02-04 11:24:54 +01:00
|
|
|
const SessionStats::Ptr& stats)
|
2011-12-11 09:28:55 +01:00
|
|
|
: Base(config, stats),
|
2011-12-17 11:53:21 +01:00
|
|
|
control_drought("control", config->now),
|
|
|
|
data_drought("data", config->now),
|
2011-12-11 09:28:55 +01:00
|
|
|
frame(config->frame),
|
|
|
|
app_bytes_(0),
|
|
|
|
net_bytes_(0),
|
|
|
|
data_bytes_(0)
|
|
|
|
{
|
|
|
|
// zero progress value
|
|
|
|
std::memset(progress_, 0, 11);
|
|
|
|
}
|
|
|
|
|
2011-12-17 11:53:21 +01:00
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
net_out.clear();
|
|
|
|
Base::reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void initial_app_send(const char *msg)
|
|
|
|
{
|
|
|
|
Base::start();
|
|
|
|
|
|
|
|
const size_t msglen = std::strlen(msg);
|
|
|
|
BufferAllocated app_buf((unsigned char *)msg, msglen, 0);
|
|
|
|
copy_progress(app_buf);
|
|
|
|
control_send(app_buf);
|
|
|
|
flush(true);
|
|
|
|
}
|
|
|
|
|
2011-12-15 09:48:14 +01:00
|
|
|
bool do_housekeeping()
|
|
|
|
{
|
2011-12-16 11:02:15 +01:00
|
|
|
if (now() >= Base::next_housekeeping())
|
2011-12-15 09:48:14 +01:00
|
|
|
{
|
|
|
|
Base::housekeeping();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
void control_send(BufferPtr& app_bp)
|
|
|
|
{
|
|
|
|
app_bytes_ += app_bp->size();
|
|
|
|
Base::control_send(app_bp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void control_send(BufferAllocated& app_buf)
|
|
|
|
{
|
|
|
|
app_bytes_ += app_buf.size();
|
|
|
|
Base::control_send(app_buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferPtr data_encrypt_string(const char *str)
|
|
|
|
{
|
|
|
|
BufferPtr bp = new BufferAllocated();
|
|
|
|
frame->prepare(Frame::READ_LINK_UDP, *bp);
|
|
|
|
bp->write((unsigned char *)str, std::strlen(str));
|
|
|
|
data_encrypt(*bp);
|
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void data_encrypt(BufferAllocated& in_out)
|
|
|
|
{
|
|
|
|
Base::data_encrypt(in_out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void data_decrypt(const PacketType& type, BufferAllocated& in_out)
|
|
|
|
{
|
|
|
|
Base::data_decrypt(type, in_out);
|
2011-12-13 05:46:56 +01:00
|
|
|
if (in_out.size())
|
2011-12-14 12:34:33 +01:00
|
|
|
{
|
|
|
|
data_bytes_ += in_out.size();
|
|
|
|
data_drought.event();
|
|
|
|
}
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t net_bytes() const { return net_bytes_; }
|
|
|
|
size_t app_bytes() const { return app_bytes_; }
|
|
|
|
size_t data_bytes() const { return data_bytes_; }
|
|
|
|
|
|
|
|
const char *progress() const { return progress_; }
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
void finalize()
|
|
|
|
{
|
|
|
|
data_drought.event();
|
|
|
|
control_drought.event();
|
|
|
|
}
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
std::deque<BufferPtr> net_out;
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
DroughtMeasure control_drought;
|
|
|
|
DroughtMeasure data_drought;
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
private:
|
|
|
|
virtual void control_net_send(const Buffer& net_buf)
|
|
|
|
{
|
|
|
|
net_bytes_ += net_buf.size();
|
|
|
|
net_out.push_back(BufferPtr(new BufferAllocated(net_buf, 0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void control_recv(BufferPtr& app_bp)
|
|
|
|
{
|
|
|
|
BufferPtr work;
|
|
|
|
work.swap(app_bp);
|
|
|
|
if (work->size() >= 23)
|
|
|
|
std::memcpy(progress_, work->data()+13, 10);
|
|
|
|
|
|
|
|
#ifdef VERBOSE
|
|
|
|
{
|
|
|
|
const ssize_t trunc = 64;
|
|
|
|
const std::string show((char *)work->data(), trunc);
|
2011-12-18 11:50:08 +01:00
|
|
|
std::cout << now().raw() << " " << mode().str() << " " << show << std::endl;
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
modmsg(work);
|
|
|
|
control_send(work);
|
2011-12-13 05:46:56 +01:00
|
|
|
control_drought.event();
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
|
2011-12-17 11:53:21 +01:00
|
|
|
void copy_progress(Buffer& buf)
|
|
|
|
{
|
|
|
|
if (progress_[0]) // make sure progress was initialized
|
|
|
|
std::memcpy(buf.data()+13, progress_, 10);
|
|
|
|
}
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
void modmsg(BufferPtr& buf)
|
|
|
|
{
|
|
|
|
char *msg = (char *) buf->data();
|
2011-12-18 11:50:08 +01:00
|
|
|
if (is_server())
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
msg[8] = 'S';
|
|
|
|
msg[11] = 'C';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msg[8] = 'C';
|
|
|
|
msg[11] = 'S';
|
|
|
|
}
|
|
|
|
|
|
|
|
// increment embedded number
|
|
|
|
for (int i = 22; i >= 13; i--)
|
|
|
|
{
|
|
|
|
if (msg[i] != '9')
|
|
|
|
{
|
|
|
|
msg[i]++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
msg[i] = '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Frame::Ptr frame;
|
|
|
|
size_t app_bytes_;
|
|
|
|
size_t net_bytes_;
|
|
|
|
size_t data_bytes_;
|
|
|
|
char progress_[11];
|
|
|
|
};
|
|
|
|
|
2014-10-16 02:12:38 +02:00
|
|
|
template <typename CRYPTO_API>
|
|
|
|
class TestProtoClient : public TestProto<CRYPTO_API>
|
2011-12-14 17:20:07 +01:00
|
|
|
{
|
2014-10-16 02:12:38 +02:00
|
|
|
typedef TestProto<CRYPTO_API> Base;
|
2011-12-14 17:20:07 +01:00
|
|
|
public:
|
|
|
|
TestProtoClient(const typename Base::Config::Ptr& config,
|
2012-02-04 11:24:54 +01:00
|
|
|
const SessionStats::Ptr& stats)
|
2011-12-14 17:20:07 +01:00
|
|
|
: Base(config, stats)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void client_auth(Buffer& buf)
|
|
|
|
{
|
|
|
|
const std::string username("foo");
|
|
|
|
const std::string password("bar");
|
2011-12-16 11:02:15 +01:00
|
|
|
Base::write_auth_string(username, buf);
|
|
|
|
Base::write_auth_string(password, buf);
|
2011-12-14 17:20:07 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-10-16 02:12:38 +02:00
|
|
|
template <typename CRYPTO_API>
|
|
|
|
class TestProtoServer : public TestProto<CRYPTO_API>
|
2011-12-14 17:20:07 +01:00
|
|
|
{
|
2014-10-16 02:12:38 +02:00
|
|
|
typedef TestProto<CRYPTO_API> Base;
|
2011-12-14 17:20:07 +01:00
|
|
|
public:
|
|
|
|
OPENVPN_SIMPLE_EXCEPTION(auth_failed);
|
|
|
|
|
|
|
|
TestProtoServer(const typename Base::Config::Ptr& config,
|
2012-02-04 11:24:54 +01:00
|
|
|
const SessionStats::Ptr& stats)
|
2011-12-14 17:20:07 +01:00
|
|
|
: Base(config, stats)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void server_auth(Buffer& buf, const std::string& peer_info)
|
|
|
|
{
|
2011-12-16 11:02:15 +01:00
|
|
|
const std::string username = Base::template read_auth_string<std::string>(buf);
|
|
|
|
const std::string password = Base::template read_auth_string<std::string>(buf);
|
2011-12-14 17:20:07 +01:00
|
|
|
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << "**** AUTHENTICATE " << username << '/' << password << " PEER INFO:" << std::endl;
|
|
|
|
std::cout << peer_info;
|
|
|
|
#endif
|
|
|
|
if (username != "foo" || password != "bar")
|
|
|
|
throw auth_failed();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// Simulate a noisy transmission channel where packets can be dropped,
|
|
|
|
// reordered, or corrupted.
|
2011-12-11 09:28:55 +01:00
|
|
|
class NoisyWire
|
|
|
|
{
|
|
|
|
public:
|
2011-12-15 09:48:14 +01:00
|
|
|
OPENVPN_SIMPLE_EXCEPTION(session_invalidated);
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
NoisyWire(const std::string title_arg,
|
|
|
|
TimePtr now_arg,
|
|
|
|
RandomIntBase& rand_arg,
|
|
|
|
const unsigned int reorder_prob_arg,
|
|
|
|
const unsigned int drop_prob_arg,
|
|
|
|
const unsigned int corrupt_prob_arg)
|
|
|
|
: title(title_arg),
|
|
|
|
now(now_arg),
|
|
|
|
random(rand_arg),
|
|
|
|
reorder_prob(reorder_prob_arg),
|
|
|
|
drop_prob(drop_prob_arg),
|
|
|
|
corrupt_prob(corrupt_prob_arg)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T1, typename T2>
|
|
|
|
void xfer(T1& a, T2& b)
|
|
|
|
{
|
2011-12-15 09:48:14 +01:00
|
|
|
// check for errors
|
|
|
|
if (a.invalidated() || b.invalidated())
|
|
|
|
throw session_invalidated();
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
// need to retransmit?
|
2011-12-15 09:48:14 +01:00
|
|
|
if (a.do_housekeeping())
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
#ifdef VERBOSE
|
2011-12-15 09:48:14 +01:00
|
|
|
std::cout << now->raw() << " " << title << " Housekeeping" << std::endl;
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// queue a data channel packet
|
|
|
|
if (a.data_channel_ready())
|
|
|
|
{
|
|
|
|
BufferPtr bp = a.data_encrypt_string("Waiting for godot...");
|
|
|
|
wire.push_back(bp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// transfer network packets from A -> wire
|
|
|
|
while (!a.net_out.empty())
|
|
|
|
{
|
|
|
|
BufferPtr bp = a.net_out.front();
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " " << a.dump_packet(*bp) << std::endl;
|
|
|
|
#endif
|
|
|
|
a.net_out.pop_front();
|
|
|
|
wire.push_back(bp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// transfer network packets from wire -> B
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
BufferPtr bp = recv();
|
|
|
|
if (!bp)
|
|
|
|
break;
|
|
|
|
typename T2::PacketType pt = b.packet_type(*bp);
|
|
|
|
if (pt.is_control())
|
2011-12-13 05:46:56 +01:00
|
|
|
{
|
|
|
|
#ifdef VERBOSE
|
|
|
|
if (!b.control_net_validate(pt, *bp)) // not strictly necessary since control_net_recv will also validate
|
|
|
|
std::cout << now->raw() << " " << title << " CONTROL PACKET VALIDATION FAILED" << std::endl;
|
|
|
|
#endif
|
|
|
|
b.control_net_recv(pt, bp);
|
|
|
|
}
|
2011-12-11 09:28:55 +01:00
|
|
|
else if (pt.is_data())
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
b.data_decrypt(pt, *bp);
|
|
|
|
#ifdef VERBOSE
|
|
|
|
if (bp->size())
|
|
|
|
{
|
|
|
|
const std::string show((char *)bp->data(), bp->size());
|
2011-12-13 05:46:56 +01:00
|
|
|
std::cout << now->raw() << " " << title << " DATA CHANNEL DECRYPT: " << show << std::endl;
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2012-02-17 20:28:44 +01:00
|
|
|
catch (const std::exception& e)
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " Exception on data channel decrypt: " << e.what() << std::endl;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-12-13 05:46:56 +01:00
|
|
|
b.flush(true);
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
BufferPtr recv()
|
|
|
|
{
|
|
|
|
// simulate packets being received out of order
|
|
|
|
if (wire.size() >= 2 && !rand(reorder_prob))
|
|
|
|
{
|
|
|
|
const size_t i = random.randrange(wire.size() - 1) + 1;
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " Simulating packet reordering " << i << " -> 0" << std::endl;
|
|
|
|
#endif
|
|
|
|
std::swap(wire[0], wire[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wire.size())
|
|
|
|
{
|
|
|
|
BufferPtr bp = wire.front();
|
|
|
|
wire.pop_front();
|
|
|
|
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " Received packet, size=" << bp->size() << std::endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// simulate dropped packet
|
|
|
|
if (!rand(drop_prob))
|
|
|
|
{
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " Simulating a dropped packet" << std::endl;
|
|
|
|
#endif
|
|
|
|
return BufferPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
// simulate corrupted packet
|
2011-12-13 05:46:56 +01:00
|
|
|
if (bp->size() && !rand(corrupt_prob))
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << now->raw() << " " << title << " Simulating a corrupted packet" << std::endl;
|
|
|
|
#endif
|
|
|
|
const size_t pos = random.randrange(bp->size());
|
|
|
|
const unsigned char value = random.randrange(256);
|
|
|
|
(*bp)[pos] = value;
|
|
|
|
}
|
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return BufferPtr();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int rand(const unsigned int prob)
|
|
|
|
{
|
|
|
|
if (prob)
|
|
|
|
return random.randrange(prob);
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string title;
|
|
|
|
TimePtr now;
|
|
|
|
RandomIntBase& random;
|
|
|
|
unsigned int reorder_prob;
|
|
|
|
unsigned int drop_prob;
|
|
|
|
unsigned int corrupt_prob;
|
|
|
|
std::deque<BufferPtr> wire;
|
|
|
|
};
|
|
|
|
|
2012-02-04 11:24:54 +01:00
|
|
|
class MySessionStats : public SessionStats
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef boost::intrusive_ptr<MySessionStats> Ptr;
|
|
|
|
|
|
|
|
MySessionStats()
|
|
|
|
{
|
|
|
|
std::memset(errors, 0, sizeof(errors));
|
|
|
|
}
|
|
|
|
|
2012-02-13 00:09:28 +01:00
|
|
|
virtual void error(const size_t err_type, const std::string* text=NULL)
|
2012-02-04 11:24:54 +01:00
|
|
|
{
|
|
|
|
if (err_type < Error::N_ERRORS)
|
|
|
|
++errors[err_type];
|
|
|
|
}
|
|
|
|
|
|
|
|
count_t get_error_count(const Error::Type type) const
|
|
|
|
{
|
|
|
|
if (type < Error::N_ERRORS)
|
|
|
|
return errors[type];
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
count_t errors[Error::N_ERRORS];
|
|
|
|
};
|
|
|
|
|
2011-12-13 12:13:27 +01:00
|
|
|
// execute the unit test in one thread
|
2012-08-31 08:50:43 +02:00
|
|
|
int test(const int thread_num)
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
// frame
|
|
|
|
Frame::Ptr frame(new Frame(Frame::Context(128, 256, 128, 0, 16, 0)));
|
|
|
|
|
|
|
|
// RNG
|
2012-03-12 13:24:40 +01:00
|
|
|
ClientRandomAPI::Ptr rng_cli(new ClientRandomAPI());
|
2014-10-15 20:53:18 +02:00
|
|
|
RandomInt rand(*rng_cli);
|
|
|
|
PRNG<ClientCryptoAPI>::Ptr prng_cli(new PRNG<ClientCryptoAPI>(STRINGIZE(PROTO_DIGEST), rng_cli, 16));
|
2012-03-12 13:24:40 +01:00
|
|
|
|
|
|
|
ServerRandomAPI::Ptr rng_serv(new ServerRandomAPI());
|
2014-10-15 20:53:18 +02:00
|
|
|
PRNG<ServerCryptoAPI>::Ptr prng_serv(new PRNG<ServerCryptoAPI>(STRINGIZE(PROTO_DIGEST), rng_serv, 16));
|
2011-12-11 09:28:55 +01:00
|
|
|
|
|
|
|
// init simulated time
|
|
|
|
Time time;
|
|
|
|
const Time::Duration time_step = Time::Duration::binary_ms(100);
|
|
|
|
|
|
|
|
// client config files
|
2013-01-30 22:08:55 +01:00
|
|
|
const std::string ca_crt = read_text("ca.crt");
|
2011-12-11 09:28:55 +01:00
|
|
|
const std::string client_crt = read_text("client.crt");
|
|
|
|
const std::string client_key = read_text("client.key");
|
|
|
|
const std::string server_crt = read_text("server.crt");
|
|
|
|
const std::string server_key = read_text("server.key");
|
|
|
|
const std::string dh_pem = read_text("dh.pem");
|
|
|
|
const std::string tls_auth_key = read_text("tls-auth.key");
|
|
|
|
|
|
|
|
// client config
|
2012-03-12 13:24:40 +01:00
|
|
|
ClientSSLAPI::Config cc;
|
2011-12-18 11:50:08 +01:00
|
|
|
cc.mode = Mode(Mode::CLIENT);
|
|
|
|
cc.frame = frame;
|
2011-12-11 09:28:55 +01:00
|
|
|
#ifdef USE_APPLE_SSL
|
2011-12-18 12:33:15 +01:00
|
|
|
cc.load_identity("etest");
|
2011-12-11 09:28:55 +01:00
|
|
|
#else
|
2013-01-30 22:08:55 +01:00
|
|
|
cc.load_ca(ca_crt);
|
2011-12-18 11:50:08 +01:00
|
|
|
cc.load_cert(client_crt);
|
|
|
|
cc.load_private_key(client_key);
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
2014-03-04 02:43:13 +01:00
|
|
|
cc.tls_version_min = TLSVersion::UNDEF;
|
2011-12-11 09:28:55 +01:00
|
|
|
#ifdef VERBOSE
|
2014-03-03 22:43:38 +01:00
|
|
|
cc.ssl_debug_level = 1;
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
2012-03-14 01:51:40 +01:00
|
|
|
#if defined(USE_POLARSSL)
|
|
|
|
cc.rng = rng_cli;
|
|
|
|
#endif
|
2011-12-11 09:28:55 +01:00
|
|
|
|
|
|
|
// client stats
|
2012-02-04 11:24:54 +01:00
|
|
|
MySessionStats::Ptr cli_stats(new MySessionStats);
|
2011-12-11 09:28:55 +01:00
|
|
|
|
|
|
|
// client ProtoContext config
|
2014-10-16 02:12:38 +02:00
|
|
|
typedef ProtoContext<ClientCryptoAPI> ClientProtoContext;
|
2011-12-11 09:28:55 +01:00
|
|
|
ClientProtoContext::Config::Ptr cp(new ClientProtoContext::Config);
|
2014-10-16 02:12:38 +02:00
|
|
|
cp->ssl_factory.reset(new ClientSSLAPI(cc));
|
2014-10-17 23:52:29 +02:00
|
|
|
cp->dc_factory.reset(new CryptoDCSelect<ClientCryptoAPI>(frame, prng_cli));
|
2011-12-11 09:28:55 +01:00
|
|
|
cp->frame = frame;
|
|
|
|
cp->now = &time;
|
2012-03-12 13:24:40 +01:00
|
|
|
cp->rng = rng_cli;
|
|
|
|
cp->prng = prng_cli;
|
2011-12-14 12:34:33 +01:00
|
|
|
cp->protocol = Protocol(Protocol::UDPv4);
|
|
|
|
cp->layer = Layer(Layer::OSI_LAYER_3);
|
2012-09-10 01:10:20 +02:00
|
|
|
cp->comp_ctx = CompressContext(CompressContext::LZO_STUB, false);
|
2012-03-26 00:07:45 +02:00
|
|
|
cp->cipher = ClientCryptoAPI::Cipher(STRINGIZE(PROTO_CIPHER));
|
|
|
|
cp->digest = ClientCryptoAPI::Digest(STRINGIZE(PROTO_DIGEST));
|
2014-10-17 23:52:29 +02:00
|
|
|
cp->set_cipher_digest();
|
2011-12-13 05:46:56 +01:00
|
|
|
#ifdef USE_TLS_AUTH
|
2011-12-11 09:28:55 +01:00
|
|
|
cp->tls_auth_key.parse(tls_auth_key);
|
2012-03-26 00:07:45 +02:00
|
|
|
cp->tls_auth_digest = ClientCryptoAPI::Digest(STRINGIZE(PROTO_DIGEST));
|
2013-01-30 17:24:37 +01:00
|
|
|
cp->key_direction = 0;
|
2011-12-13 05:46:56 +01:00
|
|
|
#endif
|
2011-12-11 09:28:55 +01:00
|
|
|
cp->reliable_window = 4;
|
|
|
|
cp->max_ack_list = 4;
|
|
|
|
cp->pid_mode = PacketIDReceive::UDP_MODE;
|
|
|
|
cp->pid_seq_backtrack = 64;
|
|
|
|
cp->pid_time_backtrack = 30;
|
2012-08-31 23:39:01 +02:00
|
|
|
#if defined(HANDSHAKE_WINDOW)
|
|
|
|
cp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW);
|
|
|
|
#elif SITER > 1
|
2011-12-17 11:53:21 +01:00
|
|
|
cp->handshake_window = Time::Duration::seconds(30);
|
|
|
|
#else
|
2011-12-15 09:48:14 +01:00
|
|
|
cp->handshake_window = Time::Duration::seconds(18); // will cause a small number of handshake failures
|
2011-12-17 11:53:21 +01:00
|
|
|
#endif
|
2011-12-13 05:46:56 +01:00
|
|
|
cp->become_primary = Time::Duration::seconds(30);
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(CLIENT_NO_RENEG)
|
|
|
|
cp->renegotiate = Time::Duration::infinite();
|
|
|
|
#else
|
2014-03-03 22:43:38 +01:00
|
|
|
cp->renegotiate = Time::Duration::seconds(RENEG);
|
2012-09-15 08:56:18 +02:00
|
|
|
#endif
|
|
|
|
cp->expire = cp->renegotiate + cp->renegotiate;
|
2011-12-15 09:48:14 +01:00
|
|
|
cp->keepalive_ping = Time::Duration::seconds(5);
|
|
|
|
cp->keepalive_timeout = Time::Duration::seconds(60);
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2011-12-14 12:34:33 +01:00
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << "CLIENT OPTIONS: " << cp->options_string() << std::endl;
|
|
|
|
std::cout << "CLIENT PEER INFO:" << std::endl;
|
|
|
|
std::cout << cp->peer_info_string();
|
|
|
|
#endif
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
// server config
|
2012-03-12 13:24:40 +01:00
|
|
|
ServerSSLAPI::Config sc;
|
2011-12-18 11:50:08 +01:00
|
|
|
sc.mode = Mode(Mode::SERVER);
|
|
|
|
sc.frame = frame;
|
2013-01-30 22:08:55 +01:00
|
|
|
sc.load_ca(ca_crt);
|
2011-12-18 11:50:08 +01:00
|
|
|
sc.load_cert(server_crt);
|
|
|
|
sc.load_private_key(server_key);
|
|
|
|
sc.load_dh(dh_pem);
|
2014-03-04 02:43:13 +01:00
|
|
|
sc.tls_version_min = TLSVersion::UNDEF;
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(USE_POLARSSL_SERVER)
|
|
|
|
sc.rng = rng_serv;
|
|
|
|
#endif
|
2011-12-11 09:28:55 +01:00
|
|
|
#ifdef VERBOSE
|
2014-03-03 22:43:38 +01:00
|
|
|
sc.ssl_debug_level = 1;
|
2011-12-11 09:28:55 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// server ProtoContext config
|
2014-10-16 02:12:38 +02:00
|
|
|
typedef ProtoContext<ServerCryptoAPI> ServerProtoContext;
|
2011-12-11 09:28:55 +01:00
|
|
|
ServerProtoContext::Config::Ptr sp(new ServerProtoContext::Config);
|
2014-10-16 02:12:38 +02:00
|
|
|
sp->ssl_factory.reset(new ServerSSLAPI(sc));
|
2014-10-17 23:52:29 +02:00
|
|
|
sp->dc_factory.reset(new CryptoDCSelect<ServerCryptoAPI>(frame, prng_serv));
|
2011-12-11 09:28:55 +01:00
|
|
|
sp->frame = frame;
|
|
|
|
sp->now = &time;
|
2012-03-12 13:24:40 +01:00
|
|
|
sp->rng = rng_serv;
|
|
|
|
sp->prng = prng_serv;
|
2011-12-14 12:34:33 +01:00
|
|
|
sp->protocol = Protocol(Protocol::UDPv4);
|
|
|
|
sp->layer = Layer(Layer::OSI_LAYER_3);
|
2012-09-10 01:10:20 +02:00
|
|
|
sp->comp_ctx = CompressContext(CompressContext::LZO_STUB, false);
|
2012-03-26 00:07:45 +02:00
|
|
|
sp->cipher = ServerCryptoAPI::Cipher(STRINGIZE(PROTO_CIPHER));
|
|
|
|
sp->digest = ServerCryptoAPI::Digest(STRINGIZE(PROTO_DIGEST));
|
2014-10-17 23:52:29 +02:00
|
|
|
sp->set_cipher_digest();
|
2011-12-13 05:46:56 +01:00
|
|
|
#ifdef USE_TLS_AUTH
|
2011-12-11 09:28:55 +01:00
|
|
|
sp->tls_auth_key.parse(tls_auth_key);
|
2012-03-26 00:07:45 +02:00
|
|
|
sp->tls_auth_digest = ServerCryptoAPI::Digest(STRINGIZE(PROTO_DIGEST));
|
2013-01-30 17:24:37 +01:00
|
|
|
sp->key_direction = 1;
|
2011-12-13 05:46:56 +01:00
|
|
|
#endif
|
2011-12-11 09:28:55 +01:00
|
|
|
sp->reliable_window = 4;
|
|
|
|
sp->max_ack_list = 4;
|
|
|
|
sp->pid_mode = PacketIDReceive::UDP_MODE;
|
|
|
|
sp->pid_seq_backtrack = 64;
|
|
|
|
sp->pid_time_backtrack = 30;
|
2012-08-31 23:39:01 +02:00
|
|
|
#if defined(HANDSHAKE_WINDOW)
|
|
|
|
sp->handshake_window = Time::Duration::seconds(HANDSHAKE_WINDOW);
|
|
|
|
#elif SITER > 1
|
2011-12-17 11:53:21 +01:00
|
|
|
sp->handshake_window = Time::Duration::seconds(30);
|
|
|
|
#else
|
2011-12-15 09:48:14 +01:00
|
|
|
sp->handshake_window = Time::Duration::seconds(17) + Time::Duration::binary_ms(512);
|
2011-12-17 11:53:21 +01:00
|
|
|
#endif
|
2011-12-15 09:48:14 +01:00
|
|
|
sp->become_primary = Time::Duration::seconds(30);
|
2012-09-15 08:56:18 +02:00
|
|
|
#if defined(SERVER_NO_RENEG)
|
|
|
|
sp->renegotiate = Time::Duration::infinite();
|
|
|
|
#else
|
2014-03-03 22:43:38 +01:00
|
|
|
sp->renegotiate = Time::Duration::seconds(RENEG);
|
2012-09-15 08:56:18 +02:00
|
|
|
#endif
|
|
|
|
sp->expire = sp->renegotiate + sp->renegotiate;
|
2011-12-15 09:48:14 +01:00
|
|
|
sp->keepalive_ping = Time::Duration::seconds(5);
|
|
|
|
sp->keepalive_timeout = Time::Duration::seconds(60);
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2011-12-14 12:34:33 +01:00
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << "SERVER OPTIONS: " << sp->options_string() << std::endl;
|
|
|
|
std::cout << "SERVER PEER INFO:" << std::endl;
|
|
|
|
std::cout << sp->peer_info_string();
|
|
|
|
#endif
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
// server stats
|
2012-02-04 11:24:54 +01:00
|
|
|
MySessionStats::Ptr serv_stats(new MySessionStats);
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2014-10-16 02:12:38 +02:00
|
|
|
TestProtoClient<ClientCryptoAPI> cli_proto(cp, cli_stats);
|
|
|
|
TestProtoServer<ServerCryptoAPI> serv_proto(sp, serv_stats);
|
2011-12-11 09:28:55 +01:00
|
|
|
|
2011-12-17 11:53:21 +01:00
|
|
|
for (int i = 0; i < SITER; ++i)
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
2011-12-17 11:53:21 +01:00
|
|
|
#ifdef VERBOSE
|
|
|
|
std::cout << "***** SITER " << i << std::endl;
|
|
|
|
#endif
|
|
|
|
cli_proto.reset();
|
|
|
|
serv_proto.reset();
|
|
|
|
|
|
|
|
NoisyWire client_to_server("Client -> Server", &time, rand, 8, 16, 32); // last value: 32
|
|
|
|
NoisyWire server_to_client("Server -> Client", &time, rand, 8, 16, 32); // last value: 32
|
|
|
|
|
2012-03-14 04:24:45 +01:00
|
|
|
int j = -1;
|
|
|
|
try {
|
|
|
|
// start feedback loop
|
|
|
|
cli_proto.initial_app_send(message);
|
|
|
|
serv_proto.start();
|
|
|
|
|
|
|
|
// message loop
|
|
|
|
for (j = 0; j < ITER; ++j)
|
|
|
|
{
|
|
|
|
client_to_server.xfer(cli_proto, serv_proto);
|
|
|
|
server_to_client.xfer(serv_proto, cli_proto);
|
|
|
|
time += time_step;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
2011-12-17 11:53:21 +01:00
|
|
|
{
|
2012-03-14 04:24:45 +01:00
|
|
|
std::cerr << "Exception[" << i << '/' << j << "]: " << e.what() << std::endl;
|
2012-08-31 08:50:43 +02:00
|
|
|
return 1;
|
2011-12-17 11:53:21 +01:00
|
|
|
}
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
cli_proto.finalize();
|
|
|
|
serv_proto.finalize();
|
|
|
|
|
2011-12-11 09:28:55 +01:00
|
|
|
const size_t ab = cli_proto.app_bytes() + serv_proto.app_bytes();
|
|
|
|
const size_t nb = cli_proto.net_bytes() + serv_proto.net_bytes();
|
|
|
|
const size_t db = cli_proto.data_bytes() + serv_proto.data_bytes();
|
|
|
|
|
2012-08-31 08:50:43 +02:00
|
|
|
std::cerr << "*** app bytes=" << ab
|
2011-12-13 05:46:56 +01:00
|
|
|
<< " net_bytes=" << nb
|
|
|
|
<< " data_bytes=" << db
|
|
|
|
<< " prog=" << cli_proto.progress() << '/' << serv_proto.progress()
|
|
|
|
<< " D=" << cli_proto.control_drought().raw() << '/' << cli_proto.data_drought().raw() << '/' << serv_proto.control_drought().raw() << '/' << serv_proto.data_drought().raw()
|
|
|
|
<< " N=" << cli_proto.negotiations() << '/' << serv_proto.negotiations()
|
2011-12-15 09:48:14 +01:00
|
|
|
<< " SH=" << cli_proto.slowest_handshake().raw() << '/' << serv_proto.slowest_handshake().raw()
|
2012-02-04 11:24:54 +01:00
|
|
|
<< " HE=" << cli_stats->get_error_count(Error::HANDSHAKE_TIMEOUT) << '/' << serv_stats->get_error_count(Error::HANDSHAKE_TIMEOUT)
|
2011-12-13 05:46:56 +01:00
|
|
|
<< std::endl;
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
2012-02-17 20:28:44 +01:00
|
|
|
catch (const std::exception& e)
|
2011-12-11 09:28:55 +01:00
|
|
|
{
|
|
|
|
std::cerr << "Exception: " << e.what() << std::endl;
|
2012-08-31 08:50:43 +02:00
|
|
|
return 1;
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|
2012-08-31 08:50:43 +02:00
|
|
|
return 0;
|
2011-12-13 05:46:56 +01:00
|
|
|
}
|
|
|
|
|
2014-03-05 01:42:00 +01:00
|
|
|
int main(int argc, char* argv[])
|
2011-12-13 05:46:56 +01:00
|
|
|
{
|
2012-03-12 13:24:40 +01:00
|
|
|
// process-wide initialization
|
|
|
|
InitProcess::init();
|
2014-03-05 01:42:00 +01:00
|
|
|
|
|
|
|
if (argc >= 2 && !strcmp(argv[1], "test"))
|
|
|
|
{
|
|
|
|
const std::string out = SelfTest::crypto_self_test();
|
|
|
|
OPENVPN_LOG(out);
|
|
|
|
return 0;
|
|
|
|
}
|
2011-12-17 06:06:39 +01:00
|
|
|
|
2011-12-13 05:46:56 +01:00
|
|
|
#if N_THREADS >= 2 && OPENVPN_MULTITHREAD
|
|
|
|
boost::thread* threads[N_THREADS];
|
2012-02-07 13:56:32 +01:00
|
|
|
int i;
|
2011-12-13 05:46:56 +01:00
|
|
|
for (i = 0; i < N_THREADS; ++i)
|
|
|
|
{
|
|
|
|
threads[i] = new boost::thread(boost::bind(&test, i));
|
|
|
|
}
|
|
|
|
for (i = 0; i < N_THREADS; ++i)
|
|
|
|
{
|
|
|
|
threads[i]->join();
|
|
|
|
delete threads[i];
|
|
|
|
}
|
2012-08-31 08:50:43 +02:00
|
|
|
return 0;
|
2011-12-13 05:46:56 +01:00
|
|
|
#else
|
2012-08-31 08:50:43 +02:00
|
|
|
return test(1);
|
2011-12-13 05:46:56 +01:00
|
|
|
#endif
|
2011-12-11 09:28:55 +01:00
|
|
|
}
|