2016-06-24 17 views
1

私は ASIO ブースト::とOpenSSLので暗号化されたネットワーク通信のための概念実証としてそれのための単純なエコーサーバとクライアントを書いていると、クライアント・サーバーの通信に失敗したことを確認します。私は両側が自己署名証明書でお互いを認証するようにします。私はそれから生成された2つの証明書で両側に同じ秘密鍵を使用しています。しかし、私はハンドシェークフェーズ次のエラーを持っている両側の間でセキュアな通信を確立しようとしたとき:証明書は、ブースト:: ASIOとOpenSSL

証明書が

まず私は、秘密鍵とサーバー証明書の両方を生成を確認に失敗しました

openssl req -x509 -newkey rsa:2048 -keyout private_key.pem -out certificate.pem -days 365 -nodes 

は、その後、私は

openssl req -newkey rsa:2048 -nodes -keyout private_key.pem -x509 -days 365 -out client_certificate.pem 
とクライアントのための追加の証明書を生成し

サーバ内のOpenSSLコンテキストの初期化は次のとおりです。

クライアントで
... 
, m_sslContext(ssl::context::sslv23) 
... 
m_sslContext.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert); 
m_sslContext.use_private_key_file(options.privateKeyFile, ssl::context::pem); 
m_sslContext.use_certificate_file(options.certificateFile, ssl::context::pem); 
... 

それは次のとおりです。

... 
, m_sslContext(ssl::context::sslv23) 
... 
m_sslContext.set_verify_mode(ssl::verify_peer); 
m_sslContext.use_private_key_file(options.privateKeyFile, ssl::context::pem); 
m_sslContext.use_certificate_file(options.certificateFile, ssl::context::pem); 
... 

サーバーの完全なコードはここにある:

#include <iostream> 
#include <iomanip> 
#include <fstream> 
#include <vector> 
#include <string> 
#include <thread> 
#include <atomic> 
#include <cstdint> 

#include <boost/asio.hpp> 
#include <boost/asio/ssl.hpp> 

#include <boost/program_options.hpp> 

#include <boost/log/core.hpp> 
#include <boost/log/trivial.hpp> 
#include <boost/log/expressions.hpp> 

#include <io_service_pool.hpp> 

using namespace std; 
using namespace boost::asio; 
using namespace boost::system; 

namespace po = boost::program_options; 
namespace logging = boost::log; 

#define CHECK_FOR_ERROR(err) \ 
    if (err) \ 
    { \ 
     BOOST_LOG_TRIVIAL(error) << err.message() << endl; \ 
     return; \ 
    } 

namespace std 
{ 

ostream& operator<<(ostream& ostr, const boost::asio::streambuf& buffer) 
{ 
    for (size_t i = 0; i < buffer.size(); ++i) 
    { 
     ostr << hex << (unsigned short) buffer_cast<const char*>(buffer.data())[i] << " "; 
    } 
    return ostr; 
} 

} // std namespace 

struct Statistics 
{ 
    atomic<uint32_t> connectionsAccepted; 
    atomic<uint32_t> requestsReceived; 
    atomic<uint32_t> responsesSent; 
    atomic<uint64_t> dataReceived; 
    atomic<uint64_t> dataSent; 

}; // Statistics struct 

Statistics g_statistics; 

class TCPConnection : public enable_shared_from_this<TCPConnection> 
{ 
public: 
    using SSLSocket = ssl::stream<ip::tcp::socket>; 
    using Ptr = shared_ptr<TCPConnection>; 

    static Ptr create(io_service& ioService, ssl::context& sslContext) 
    { 
     return TCPConnection::Ptr(new TCPConnection(ioService, sslContext)); 
    } 

    SSLSocket::lowest_layer_type& socket() 
    { 
     return m_socket.lowest_layer(); 
    } 

    void start() 
    { 
     ip::tcp::no_delay noDelay(true); 
     socket().set_option(noDelay); 

     auto remoteAddress = socket().remote_endpoint().address().to_string(); 
     BOOST_LOG_TRIVIAL(debug) << "Incoming connection from: " << remoteAddress; 

     g_statistics.connectionsAccepted++; 

     auto self(shared_from_this()); 

     m_socket.async_handshake(ssl::stream_base::server, [self, remoteAddress](const error_code& err) 
     { 
      CHECK_FOR_ERROR(err) 

      BOOST_LOG_TRIVIAL(debug) << "Handshake with " << remoteAddress << " succeeded."; 

      async_read_until(self->m_socket, self->m_buffer, '\0', 
          [self, remoteAddress](const error_code& err, size_t bytesTransfered) 
      { 
       CHECK_FOR_ERROR(err) 
       BOOST_LOG_TRIVIAL(debug) << "Received " << bytesTransfered << " bytes from " << remoteAddress; 
       BOOST_LOG_TRIVIAL(trace) << "Data: " << self->m_buffer; 

       g_statistics.requestsReceived++; 
       g_statistics.dataReceived += bytesTransfered; 

       async_write(self->m_socket, self->m_buffer, 
          [self, remoteAddress](const error_code& err, size_t bytesTransfered) 
       { 
        CHECK_FOR_ERROR(err) 
        BOOST_LOG_TRIVIAL(debug) << "Sent " << dec << bytesTransfered << " bytes to " << remoteAddress; 

        g_statistics.responsesSent++; 
        g_statistics.dataSent += bytesTransfered; 
       }); 
      }); 
     }); 
    } 

private: 
    TCPConnection(io_service& ioService, ssl::context& sslContext) 
     : m_socket(ioService, sslContext) 
    { 
    } 

private: 
    SSLSocket m_socket; 
    boost::asio::streambuf m_buffer; 

}; // TCPConnection class 

struct ProgramOptions 
{ 
    unsigned port   = 0; 
    unsigned threadsCount = 0; 
    string privateKeyFile; 
    string certificateFile; 

}; // ProgramOptions struct 

class Server 
{ 
public: 
    Server(const ProgramOptions& options) 
     : m_ioServicePool(options.threadsCount) 
     , m_acceptor(m_ioServicePool.getIOService(), 
        ip::tcp::endpoint(ip::tcp::v4(), options.port)) 
     , m_signals(m_ioServicePool.getIOService()) 
     , m_sslContext(ssl::context::sslv23) 
    { 
     m_acceptor.set_option(ip::tcp::acceptor::reuse_address(true)); 

     m_signals.add(SIGINT); 
     m_signals.add(SIGTERM); 
     m_signals.add(SIGQUIT); 
     m_signals.async_wait([this](const error_code& err, int signalNumber) 
     { 
      if (err) 
      { 
       BOOST_LOG_TRIVIAL(error) << err.message(); 
      } 

      BOOST_LOG_TRIVIAL(debug) << "Received signal: " << signalNumber; 

      BOOST_LOG_TRIVIAL(info) << "Statistics:"; 
      BOOST_LOG_TRIVIAL(info) << "Connections accepted: " << g_statistics.connectionsAccepted; 
      BOOST_LOG_TRIVIAL(info) << "Requests received: " << g_statistics.requestsReceived; 
      BOOST_LOG_TRIVIAL(info) << "Responses sent: " << g_statistics.responsesSent; 
      BOOST_LOG_TRIVIAL(info) << "Data received: " << g_statistics.dataReceived << " bytes."; 
      BOOST_LOG_TRIVIAL(info) << "Data sent: " << g_statistics.dataSent << " bytes."; 

      m_ioServicePool.stop(); 
     }); 

     m_sslContext.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert); 
     m_sslContext.use_private_key_file(options.privateKeyFile, ssl::context::pem); 
     m_sslContext.use_certificate_file(options.certificateFile, ssl::context::pem); 

     startAccept(); 
    } 

    void run() 
    { 
     BOOST_LOG_TRIVIAL(info) << "Server started!"; 
     m_ioServicePool.run(); 
    } 

private: 
    void startAccept() 
    { 
     auto conn = TCPConnection::create(m_ioServicePool.getIOService(), m_sslContext); 

     m_acceptor.async_accept(conn->socket(), [this, conn](const error_code& err) 
     { 
      CHECK_FOR_ERROR(err) 
      conn->start(); 

      startAccept(); 
     }); 
    } 

private: 
    IOServicePool m_ioServicePool; 
    ip::tcp::acceptor m_acceptor; 
    signal_set m_signals; 
    ssl::context m_sslContext; 

}; // Server class 

#undef CHECK_FOR_ERROR 

#define SET_SEVERITY_FILTER(svrt) \ 
    logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::svrt); 

void setLoggerSeverity(const string& loggerSeverity, 
         const po::options_description& options) 
{ 
    if ("trace" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(trace) 
    } 
    else if ("debug" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(debug) 
    } 
    else if ("info" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(info) 
    } 
    else if ("warning" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(warning) 
    } 
    else if ("error" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(error) 
    } 
    else if ("fatal" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(fatal) 
    } 
    else 
    { 
     cerr << "Error: Invalid logger severity: " << loggerSeverity << endl << endl; 
     cerr << options << endl; 
     exit(1); 
    } 
} 

#undef SET_SEVERITY_FILTER 

void readProgramOptions(int argc, char* argv[], ProgramOptions& options) 
{ 
    string configFileName; 
    string loggerSeverity; 

    po::options_description genericOptions("Generic options"); 
    genericOptions.add_options() 
     ("help,h", "Produce help message.") 
     ("config,c", po::value<string>(&configFileName), 
     "Name of a file of a configuration."); 

    po::options_description configOptions("Configuration"); 
    configOptions.add_options() 
     ("port,p", po::value<unsigned>(&options.port), "Port on which the server listens.") 
     ("threads_count,t", po::value<unsigned>(&options.threadsCount)->default_value(0), 
     "Number of server threads. 0 for to use hardware threads count.") 
     ("private_key_file,r", po::value<string>(&options.privateKeyFile)->default_value("private_key.pem"), 
     "Server private key file name.") 
     ("certificate_file,e", po::value<string>(&options.certificateFile)->default_value("certificate.pem"), 
     "Server certificate file name.") 
     ("log_severity,l", po::value<string>(&loggerSeverity)->default_value("info"), 
     "Minimum severity of the log messages: [trace, debug, info, warning, error, fatal]"); 

    po::options_description commandLineOptions("Allowed options"); 
    commandLineOptions.add(genericOptions).add(configOptions); 

    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, commandLineOptions), vm); 
    po::notify(vm); 

    if (vm.count("config")) 
    { 
     ifstream configFile(configFileName); 
     if (!configFile) 
     { 
      cerr << "Error: Can not open config file: " << configFileName << endl; 
      exit(1); 
     } 
     else 
     { 
      po::store(po::parse_config_file(configFile, configOptions), vm); 
      po::notify(vm); 
     } 
    } 

    if (vm.count("help")) 
    { 
     cout << commandLineOptions << endl; 
     exit(1); 
    } 

    if (0 == options.threadsCount) 
    { 
     options.threadsCount = thread::hardware_concurrency(); 
    } 

    if (!vm.count("port")) 
    { 
     cerr << "Error: Must specify port on which the server listens!" << endl << endl; 
     cerr << commandLineOptions << endl; 
     exit(1); 
    } 

    setLoggerSeverity(loggerSeverity, commandLineOptions); 

    BOOST_LOG_TRIVIAL(info) << "Configuration:"; 
    BOOST_LOG_TRIVIAL(info) << "Listening port: " << options.port; 
    BOOST_LOG_TRIVIAL(info) << "Worker threads count: " << options.threadsCount; 
    BOOST_LOG_TRIVIAL(info) << "Private key file name: " << options.privateKeyFile; 
    BOOST_LOG_TRIVIAL(info) << "Certificate file name: " << options.certificateFile; 
} 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
     ProgramOptions programOptions; 
     readProgramOptions(argc, argv, programOptions); 

     Server server(programOptions); 
     server.run(); 
    } 
    catch (const exception& e) 
    { 
     BOOST_LOG_TRIVIAL(fatal) << e.what();; 
    } 
    catch (...) 
    { 
     BOOST_LOG_TRIVIAL(fatal) << "Unknown error!!!" << endl; 
    } 

    return 0; 
} 

クライアントコードは次のとおりです。

#include <iostream> 
#include <fstream> 
#include <string> 
#include <thread> 
#include <atomic> 
#include <cstdint> 

#include <boost/asio.hpp> 
#include <boost/asio/ssl.hpp> 

#include <boost/program_options.hpp> 

#include <boost/log/core.hpp> 
#include <boost/log/trivial.hpp> 
#include <boost/log/expressions.hpp> 

#include <io_service_pool.hpp> 
#include <speed_limiter.hpp> 

using namespace std; 
using namespace boost::asio; 
using namespace boost::system; 

namespace po = boost::program_options; 
namespace logging = boost::log; 

#define CHECK_FOR_ERROR(err) \ 
    if (err) \ 
    { \ 
     BOOST_LOG_TRIVIAL(error) << err.message() << endl; \ 
     return; \ 
    } 

namespace std 
{ 

ostream& operator<<(ostream& ostr, const boost::asio::streambuf& buffer) 
{ 
    for (size_t i = 0; i < buffer.size(); ++i) 
    { 
     ostr << hex << (unsigned short) buffer_cast<const char*>(buffer.data())[i] << " "; 
    } 
    return ostr; 
} 

} // std namespace 

string generateRandomData(size_t size) 
{ 
    static random_device randomDevice; 
    static default_random_engine randomEngine(randomDevice()); 
    static uniform_int_distribution<unsigned char> randomByte(1, 255); 

    string data; 
    data.reserve(size); 

    for (size_t i = 0; i < size - 1; ++i) 
    { 
     data += randomByte(randomEngine); 
    } 
    data += '\0'; 

    return data; 
} 

struct Statistics 
{ 
    atomic<uint32_t> connectionsEstablished; 
    atomic<uint32_t> requestsSent; 
    atomic<uint32_t> responsesReceived; 
    atomic<uint64_t> dataSent; 
    atomic<uint64_t> dataReceived; 

}; // Statistics struct 

Statistics g_statistics; 

void printStatistics() 
{ 
    BOOST_LOG_TRIVIAL(info) << "Statistics:"; 
    BOOST_LOG_TRIVIAL(info) << "Connections established: " << g_statistics.connectionsEstablished; 
    BOOST_LOG_TRIVIAL(info) << "Requests sent: " << g_statistics.requestsSent; 
    BOOST_LOG_TRIVIAL(info) << "Responses received: " << g_statistics.requestsSent; 
    BOOST_LOG_TRIVIAL(info) << "Data sent: " << g_statistics.dataSent << " bytes."; 
    BOOST_LOG_TRIVIAL(info) << "Data received: " << g_statistics.dataReceived << " bytes."; 
} 

class TCPConnection : public enable_shared_from_this<TCPConnection> 
{ 
public: 
    using SSLSocket = ssl::stream<ip::tcp::socket>; 
    using Ptr = shared_ptr<TCPConnection>; 

    static Ptr create(io_service& ioService, ssl::context& sslContext) 
    { 
     return TCPConnection::Ptr(new TCPConnection(ioService, sslContext)); 
    } 

    SSLSocket::lowest_layer_type& socket() 
    { 
     return m_socket.lowest_layer(); 
    } 

    void setSendData(const std::string& data) 
    { 
     ostream stream(&m_writeBuffer); 
     stream.write(data.data(), data.size()); 
    } 

    void startConnect(ip::tcp::resolver::iterator endpointIter) 
    { 
     if (endpointIter != ip::tcp::resolver::iterator()) 
     { 
      BOOST_LOG_TRIVIAL(debug) << "Trying " << endpointIter->endpoint() << " ..."; 

      auto self(shared_from_this()); 

      socket().async_connect(endpointIter->endpoint(), [self, endpointIter](const error_code& err) mutable 
      { 
       if (!err) 
       { 
        ip::tcp::no_delay noDelay(true); 
        self->socket().set_option(noDelay); 

        auto endpoint = endpointIter->endpoint(); 

        BOOST_LOG_TRIVIAL(debug) << "Connected to " << endpoint; 

        g_statistics.connectionsEstablished++; 

        self->m_socket.async_handshake(ssl::stream_base::client, [self, endpoint](const error_code& err) 
        { 
         CHECK_FOR_ERROR(err) 

         BOOST_LOG_TRIVIAL(debug) << "Handshake with " << endpoint << " succeeded."; 

         async_write(self->m_socket, self->m_writeBuffer, 
            [self, endpoint](const error_code& err, size_t bytesTransfered) 
         { 
          CHECK_FOR_ERROR(err) 
          BOOST_LOG_TRIVIAL(debug) << "Sent " << bytesTransfered << " bytes to " << endpoint; 

          g_statistics.requestsSent++; 
          g_statistics.dataSent += bytesTransfered; 

          async_read_until(self->m_socket, self->m_readBuffer, '\0', 
             [self, endpoint](const error_code& err, size_t bytesTransfered) 
          { 
           CHECK_FOR_ERROR(err) 
           BOOST_LOG_TRIVIAL(debug) << "Received " << bytesTransfered 
                 << " bytes from " << endpoint; 
           BOOST_LOG_TRIVIAL(trace) << "Data: " << self->m_readBuffer; 

           g_statistics.responsesReceived++; 
           g_statistics.dataReceived += bytesTransfered; 
          }); 
         }); 
        }); 
       } 
       else 
       { 
        BOOST_LOG_TRIVIAL(error) << err.message(); 
        self->startConnect(++endpointIter); 
       } 
      }); 
     } 
     else 
     { 
      BOOST_LOG_TRIVIAL(warning) << "There are no more endpoints to try. Shut down the client."; 
      socket().close(); 
     } 
    } 

private: 
    TCPConnection(io_service& ioService, ssl::context& sslContext) 
     : m_socket(ioService, sslContext) 
    { 
    } 

private: 
    SSLSocket m_socket; 
    boost::asio::streambuf m_writeBuffer; 
    boost::asio::streambuf m_readBuffer; 

}; // TCPConnection class 

struct ProgramOptions 
{ 
    string serverIP; 
    string privateKeyFile; 
    string certificateFile; 
    unsigned serverPort  = 0; 
    unsigned requestSize  = 0; 
    unsigned threadsCount  = 0; 
    unsigned totalRequests  = 0; 
    unsigned requestsPerSecond = 0; 

}; // ProgramOptions struct 

class Client 
{ 
public: 
    Client(const ProgramOptions& options) 
     : m_requestSize(options.requestSize) 
     , m_totalRequests(options.totalRequests) 
     , m_requestsPerSecond(options.requestsPerSecond) 
     , m_ioServicePool(options.threadsCount) 
     , m_resolver(m_ioServicePool.getIOService()) 
     , m_sslContext(ssl::context::sslv23) 

    { 
     ip::tcp::resolver::query query(options.serverIP, to_string(options.serverPort)); 

     m_resolver.async_resolve(query, [this](const error_code& err, ip::tcp::resolver::iterator endpointIter) 
     { 
      CHECK_FOR_ERROR(err) 

      m_dispatcherThread = thread([this, endpointIter]() 
      { 
       SpeedLimiter<> speedLimiter(m_requestsPerSecond); 

       for (unsigned i = 0; i < m_totalRequests; ++i) 
       { 
        auto conn = TCPConnection::create(m_ioServicePool.getIOService(), m_sslContext); 
        conn->setSendData(generateRandomData(m_requestSize)); 

        conn->startConnect(endpointIter); 

        if (m_requestsPerSecond != 0) 
         speedLimiter.limit(); 
       } 

       this_thread::sleep_for(chrono::seconds(1)); 
       m_ioServicePool.stop(); 
      }); 
     }); 

     m_sslContext.set_verify_mode(ssl::verify_peer); 
     m_sslContext.use_private_key_file(options.privateKeyFile, ssl::context::pem); 
     m_sslContext.use_certificate_file(options.certificateFile, ssl::context::pem); 
    } 

    ~Client() 
    { 
     m_dispatcherThread.join(); 
    } 

    void run() 
    { 
     BOOST_LOG_TRIVIAL(info) << "Client started!"; 
     m_ioServicePool.run(); 
    } 

private: 
    unsigned m_requestSize; 
    unsigned m_totalRequests; 
    unsigned m_requestsPerSecond; 

    IOServicePool m_ioServicePool; 
    ip::tcp::resolver m_resolver; 
    thread m_dispatcherThread; 
    ssl::context m_sslContext; 

}; // Client class 

#define SET_SEVERITY_FILTER(svrt) \ 
    logging::core::get()->set_filter(logging::trivial::severity >= logging::trivial::svrt); 

void setLoggerSeverity(const string& loggerSeverity, 
         const po::options_description& options) 
{ 
    if ("trace" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(trace) 
    } 
    else if ("debug" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(debug) 
    } 
    else if ("info" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(info) 
    } 
    else if ("warning" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(warning) 
    } 
    else if ("error" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(error) 
    } 
    else if ("fatal" == loggerSeverity) 
    { 
     SET_SEVERITY_FILTER(fatal) 
    } 
    else 
    { 
     cerr << "Error: Invalid logger severity: " << loggerSeverity << endl << endl; 
     cerr << options << endl; 
     exit(1); 
    } 
} 

#undef SET_SEVERITY_FILTER 

void readProgramOptions(int argc, char* argv[], ProgramOptions& options) 
{ 
    string configFileName; 
    string loggerSeverity; 

    po::options_description genericOptions("Generic options"); 
    genericOptions.add_options() 
     ("help,h", "Produce help message.") 
     ("config,c", po::value<string>(&configFileName), 
     "Name of a file of a configuration."); 

    po::options_description configOptions("Configuration"); 
    configOptions.add_options() 
     ("ip,i", po::value<string>(&options.serverIP), "IP address of the server.") 
     ("port,p", po::value<unsigned>(&options.serverPort), "Port number of the server.") 
     ("threads_count,t", po::value<unsigned>(&options.threadsCount)->default_value(0), 
     "Number of client threads. 0 for to use hardware threads count.") 
     ("private_key_file,r", po::value<string>(&options.privateKeyFile)->default_value("private_key.pem"), 
     "Client private key file name.") 
     ("certificate_file,e", po::value<string>(&options.certificateFile)->default_value("certificate.pem"), 
     "Client certificate file name.") 
     ("request_size,m", po::value(&options.requestSize), "The size of the request in bytes.") 
     ("total_requests,t", po::value(&options.totalRequests), "The total number of requests to be send.") 
     ("requests_per_second,s", po::value(&options.requestsPerSecond)->default_value(0), 
     "Speed in which requests are send. 0 for unlimited speed.") 
     ("log_severity,l", po::value<string>(&loggerSeverity)->default_value("info"), 
     "Minimum severity of the log messages: [trace, debug, info, warning, error, fatal]"); 

    po::options_description commandLineOptions("Allowed options"); 
    commandLineOptions.add(genericOptions).add(configOptions); 

    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, commandLineOptions), vm); 
    po::notify(vm); 

    if (vm.count("config")) 
    { 
     ifstream configFile(configFileName); 
     if (!configFile) 
     { 
      cerr << "Error: Can not open config file: " << configFileName << endl; 
      exit(1); 
     } 
     else 
     { 
      po::store(po::parse_config_file(configFile, configOptions), vm); 
      po::notify(vm); 
     } 
    } 

    if (vm.count("help")) 
    { 
     cout << commandLineOptions << endl; 
     exit(1); 
    } 

    if (0 == options.threadsCount) 
    { 
     options.threadsCount = thread::hardware_concurrency(); 
    } 

    if (!vm.count("ip")) 
    { 
     cerr << "Error: Must specify the IP address of the server!" << endl << endl; 
     cerr << commandLineOptions << endl; 
     exit(1); 
    } 

    if (!vm.count("port")) 
    { 
     cerr << "Error: Must specify port on which to connect!" << endl << endl; 
     cerr << commandLineOptions << endl; 
     exit(1); 
    } 

    if (!vm.count("request_size")) 
    { 
     cerr << "Error: Must specify bytes size of the request!" << endl << endl; 
     cerr << commandLineOptions << endl; 
     exit(1); 
    } 

    setLoggerSeverity(loggerSeverity, commandLineOptions); 

    BOOST_LOG_TRIVIAL(info) << "Configuration:"; 
    BOOST_LOG_TRIVIAL(info) << "Server IP: " << options.serverIP; 
    BOOST_LOG_TRIVIAL(info) << "Server port: " << options.serverPort; 
    BOOST_LOG_TRIVIAL(info) << "Threads count: " << options.threadsCount; 
    BOOST_LOG_TRIVIAL(info) << "Private key file name: " << options.privateKeyFile; 
    BOOST_LOG_TRIVIAL(info) << "Certificate file name: " << options.certificateFile; 
    BOOST_LOG_TRIVIAL(info) << "Request size: " << options.requestSize; 
    BOOST_LOG_TRIVIAL(info) << "Total requests: " << options.totalRequests; 
    BOOST_LOG_TRIVIAL(info) << "Requests per second: " 
          << (options.requestsPerSecond == 0 ? "unlimited" : to_string(options.requestsPerSecond)); 
} 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
     ProgramOptions programOptions; 
     readProgramOptions(argc, argv, programOptions); 

     Client client(programOptions); 
     client.run(); 

     printStatistics(); 
    } 
    catch (const exception& e) 
    { 
     BOOST_LOG_TRIVIAL(fatal) << e.what();; 
    } 
    catch (...) 
    { 
     BOOST_LOG_TRIVIAL(fatal) << "Unknown error!!!" << endl; 
    } 

    return 0; 
} 

答えて

2

use_certificate_file()およびuse_private_key_file()は、ピアに公開鍵を提供し、ピアが返すものを復号化できますが、検証を処理しません。 add_certificate_authority()add_verify_path()load_verify_file()set_default_verify_paths()、およびset_verify_callback()のいずれか(またはそれ以上)を使用して信頼確認を構成する必要があります。おそらくload_verify_file()のように見えます。

ピア証明書を確認するために秘密鍵が使用されていると誤解されているようです。そうではありません - 鍵は署名の検証には使用されず、通常はクライアントとサーバの秘密鍵が異なります。 CA証明書は、ピア証明書の検証に使用されます。あなたの場合は、自己署名証明書を使用しているため、CA証明書とピア証明書は同じです。各側は検証のためにもう一方の証明書をロードする必要があります。

関連する問題