повысить asio SSL stream.shutdown (ec);всегда была ошибка, которая является boost :: asio :: ssl :: error :: stream_truncated - PullRequest
0 голосов
/ 25 октября 2018

Я пытался использовать Boost Asio и Openssl для отправки некоторого json на SSL-сервер, в моем случае всегда возникала проблема с проблемой boost :: asio :: ssl :: error :: stream_truncated при попытке закрытьстрим, теперь я пытался игнорировать проблему, я понятия не имею, если я должен игнорировать это или что я сделал неправильно?буст версия 1.68.0, Openssl версия 1.1.1, VS 2017 CE, Windows 7 x64,

вот мой код

#include "root_certificates.hpp"
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <time.h>
#include<fstream>
#include <ctime>
#include <istream>

   int postsslserver()
  {
     try
     {
       auto const host ="mydomain.com";
        auto const port = "https";
        auto const target ="/apps/postpage.html" ;
        retcode = 0;



        setlocale(LC_ALL, "");

        pwmd5hashed = "mysecret";

        std::string jsondata ="\"Double\":12.0000001,";

        int version =11;

         // The io_context is required for all I/O
        boost::asio::io_context ioc;

        // The SSL context is required, and holds certificates
        ssl::context ctx{ ssl::context::sslv23_client };

         //20181021
        ctx.set_default_verify_paths();

        // This holds the root certificate used for verification
        //load_root_certificates(ctx);

         // Verify the remote server's certificate
        //ctx.set_verify_mode(ssl::verify_peer);
        ctx.set_verify_mode(ssl::verify_none);

        // These objects perform our I/O
        tcp::resolver resolver{ ioc };
        ssl::stream<tcp::socket> stream{ ioc, ctx };

       // Set SNI Hostname (many hosts need this to handshake successfully)
       if (!SSL_set_tlsext_host_name(stream.native_handle(), host))
       {
            boost::system::error_code ec{ static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
             throw boost::system::system_error{ ec };
        }

        // Look up the domain name
        auto const results = resolver.resolve(host, port);

        // Make the connection on the IP address we get from a lookup
        boost::asio::connect(stream.next_layer(), results.begin(), results.end());

        // Perform the SSL handshake
        stream.handshake(ssl::stream_base::client);// error always occured this line of code,the error hints was "handshake: certificate verify failed"

         // Set up an HTTP POST request message
        http::request<http::string_body> req{ http::verb::post, target, version };
        req.set(http::field::host, host);
        req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
        req.set(http::field::content_type, "application/json");
        req.set(http::field::body, jsondata);

        // Send the HTTP request to the remote host
        http::write(stream, req);

        // This buffer is used for reading and must be persisted
        boost::beast::flat_buffer buffer;

         // Declare a container to hold the response
         http::response<http::dynamic_body> res;

         // Receive the HTTP response
          http::read(stream, buffer, res);

       // Write the message to standard out
       std::cout << res << std::endl;

       // Gracefully close the stream
        boost::system::error_code ec;
        stream.shutdown(ec);// the problem was here! it always get boost::asio::ssl::error::stream_truncated issue
        if (ec == boost::asio::error::eof)
       {
        // Rationale:

            ec.assign(0, ec.category());
        }
         if (ec!= boost::asio::ssl::error::stream_truncated)//then I tried to ignore it
         {
              std::cout << ec.message()<< endl;
              throw boost::system::system_error{ ec };
          }

        // If we get here then the connection is closed gracefully
    }
   catch (std::exception const& e)
   {
    //std::cerr << "Error: " << e.what() << std::endl;
        write_text_to_log_file(e.what());
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

большое спасибо

1 Ответ

0 голосов
/ 26 октября 2018

Правильный способ безопасного отключения сокета SSL - это не прямая попытка shutdown его.

Сначала вам нужно cancel выполнить любые возможные невыполненные операции, затем инициировать shutdown и close сокет впоследствии.

Вот фрагмент рабочего решения:

virtual void OnClose(boost::system::error_code &ec)
{
    //...
    _socket.lowest_layer().cancel(ec);
    _socket.async_shutdown(std::bind(&Socket<T>::ShutdownHandler, this->shared_from_this(), std::placeholders::_1));
    //...
}

void ShutdownHandler(const boost::system::error_code &ec)
{
    //On async_shutdown both parties send and receive a 'close_notify' message.
    //When the shutdown has been negotiated by both parties, the underlying
    //transport may either be reused or closed.
    //The initiator of the shutdown will enter the shutdown-handler with an
    //error value of eof. (Socket was securely shutdown)
    if (ec && ec != boost::asio::error::eof)
    {
        LogError(ec, Error::ErrorLocation(__FUNCTION__, __LINE__));
    }

    boost::system::error_code ec2;
    _socket.lowest_layer().close(ec2);
    if (ec2)
        LogError(ec2, Error::ErrorLocation(__FUNCTION__, __LINE__));
    _shutdownComplete.exchange(true);
}

Также: boost asio ssl async_shutdown всегда завершается с ошибкой?

...