SSL证书和Boost ASIO [英] SSL certificates and Boost asio

查看:1364
本文介绍了SSL证书和Boost ASIO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我试图下载从通过C ++使用HTTPS网页内容。我来自Boost ASIO例子采取非常基本的客户端程序编译和运行良好,但是当我与谷歌测试如:www.google.co.uk/?gws_rd=ssl,它给我的错误握手:证书验证失败 。

我想这是因为ctx.set_default_verify_paths()不包含谷歌的证书(我在Windows上)的路径。

我的非常的新SSL,请你能帮助我以下的问题:

1)当我安装了OpenSSL,没坚持下来我的电脑上值得信赖的认证机构的名单?如果有,什么会导致谷歌的证书不被验证?

2),反正是有说我不关心验证,进行连接无论如何,当你在Firefox中手动添加一个例外是怎样的?我不是因为我不发送任何需要保密的连接是否可信特别感兴趣。

答案要么是大大AP preciated!

 的#include<&iostream的GT;
#包括LT&;&的IStream GT;
#包括LT&;&ostream的GT;
#包括LT&;&的fstream GT;
#包括LT&;串GT;
#包括LT&;升压/ asio.hpp>
#包括LT&;升压/ ASIO / ssl.hpp>使用boost ::支持ASIO ::知识产权:: TCP;
命名空间SSL =提高:: ASIO :: SSL;
SSL的typedef ::流< TCP ::插座> ssl_socket;INT主(INT ARGC,CHAR *的argv [])
{
  尝试
  {
如果(argc个!= 3)
{
  性病::法院LT&;< ARGC;
  性病::法院LT&;< 用法:sync_client<服务器与GT;<路径> \\ N的;
  性病::法院LT&;< 例子:\\ n;
  性病::法院LT&;< sync_client www.boost.org /LICENSE_1_0.txt\

  返回1;
}提高:: ASIO :: io_service对象io_service对象;//创建一个使用默认路径的上下文
//找到CA证书。
SSL ::上下文CTX(SSL ::环境:: sslv23);
ctx.set_default_verify_paths();//取得对应于服务器名称端点的列表。
TCP ::解析器解析(io_service对象);
TCP ::解析器::查询查询(的argv [1],https开头);
TCP ::解析:迭代endpoint_iterator = resolver.resolve(查询);//尝试每个端点,直到我们成功地建立连接。
ssl_socket插座(io_service对象,CTX);
提高:: ASIO ::连接(socket.lowest_layer(),endpoint_iterator);
。socket.lowest_layer()set_option(TCP :: no_delay(真));//执行SSL握手并检验远程主机的
// 证书。
socket.set_verify_mode(SSL :: verify_peer);
socket.set_verify_callback(SSL :: rfc2818_verification(host.name));
socket.handshake(ssl_socket ::客户端);//形式请求​​。我们指定连接:关闭的标头,这样的
//服务器将发送响应后关闭套接字。这会
//让我们起来把所有的数据,直到EOF的内容。
提高:: ASIO ::流缓冲请求;
的std :: ostream的request_stream(安培;要求);
request_stream<< GET<<的argv [2]<< HTTP / 1.0 \\ r \\ n;
request_stream<< 主持人:<<的argv [1];&下; \\ r \\ n;
request_stream<< 接受:* / * \\ r \\ n;
request_stream<< 连接:关闭\\ r \\ n \\ r \\ n;//发送请求。
提高:: ASIO ::写(插座,请求);//读取响应状态行。响应流缓冲自动将
//增长,以适应整行。该增长可能通过传递限制
//最大尺寸的流缓冲构造。
提高:: ASIO ::流缓冲响应;
提高:: ASIO :: read_until(插座,响应为\\ r \\ n);//检查响应确定。
的std :: istream的response_stream(安培;响应);
标准::字符串http_version;
response_stream>> http_version;
无符号整型状态_ code;
response_stream>>状态_ code;
标准::字符串STATUS_MESSAGE;
的std ::函数getline(response_stream,STATUS_MESSAGE);如果(!response_stream || http_version.substr(0,5)!=HTTP /)
{
  性病::法院LT&;< 无效的响应\\ n;
  返回1;
}
如果(状态_ code!= 200)
{
    性病::法院LT&;< 响应返回了状态code<<状态_ code<< \\ n;
    性病::法院LT&;< STATUS_MESSAGE<< \\ n;
    //读取响应头,这是由一个空行终止。
    提高:: ASIO :: read_until(插座,响应为\\ r \\ n \\ r \\ n);    //处理响应头。
    标准::字符串头;
    而(的std ::函数getline(response_stream,头)及和放大器;!标题=\\ r)
        性病::法院LT&;<头<< \\ n;
    性病::法院LT&;< \\ n;
      返回1;
}
// code读取数据放在这里,这对于HTTP页面正常工作
  }
  赶上(性病::例外急症)
  {
    性病::法院LT&;< 例外:<< e.what()&所述;&下; \\ n;
  }
  返回0;
}


解决方案

大多数的OpenSSL安装将安装可信证书作为安装过程的一部分,<一个href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/ssl__context/set_default_verify_paths.html\"相对=nofollow> 提高:: ASIO :: SSL ::环境:: set_default_verify_paths() 是在找到正确的路径相当不错的。

认证验证失败,因为客户端试图验证对方的验证主机名证书( RFC2818 ),并检查文字host.name是证书中,服务器的证书不列出主机。名称作为名字。尝试改变:

socket.set_verify_callback(SSL :: rfc2818_verification(host.name));

socket.set_verify_callback(SSL :: rfc2818_verification(的argv [1]));


要禁用同行验证,提供 提高:: ASIO :: SSL :: VERIFY_NONE 到<一个href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/ssl__stream/set_verify_mode/overload1.html\"相对=nofollow> 的boost ::支持ASIO :: SSL ::流:: set_verify_mode()

socket.set_verify_mode(提高:: ASIO :: SSL :: VERIFY_NONE);

Boost.Asio的提供其他同行 verify_mode 秒。


在同行验证失败,它可以帮助提供自定义的回调<一个href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/ssl__stream/set_verify_callback/overload1.html\"相对=nofollow> 的boost ::支持ASIO :: SSL ::流:: set_verify_callback 提供诊断信息。正如文件中指出,处理程序签名必须是:

布尔verify_callback(
  布尔preverified,//真如果证书通过pre-验证。
  verify_context&安培; CTX //将对方的证书和其他方面。
);

下面是打印证书使用者名称自定义函数对象:

/// @简短的助手类,显示当前证书的主题
///名称和验证结果。
模板&LT; TYPENAME验证&GT;
类verbose_verification
{
上市:
  verbose_verification(验证验证)
    :verifier_(验证)
  {}  布尔运算符()(
    布尔preverified,
    提高:: ASIO :: SSL :: verify_context&安培; CTX
  )
  {
    焦炭SUBJECT_NAME [256];
    X509 *证书= X509_STORE_CTX_get_current_cert(ctx.native_handle());
    X509_NAME_oneline(X509_get_subject_name(CERT),SUBJECT_NAME,256);
    布尔验证=验证_(preverified,CTX);
    性病::法院LT&;&LT; 验证:&LT;&LT; SUBJECT_NAME&LT;&LT; \\ n
                 验证:&LT;&LT;验证&LT;&LT;的std :: ENDL;
    返回验证;
  }
私人的:
  验证verifier_;
};/// @简短的辅助功能,使verbose_verification对象。
模板&LT; TYPENAME验证&GT;
verbose_verification&LT;&验证GT;
make_verbose_verification(验证验证)
{
  返回verbose_verification&LT;&验证GT;(验证);
}

和其用法:

socket.set_verify_callback(make_verbose_verification(
  提高:: ASIO :: SSL :: rfc2818_verification(的argv [1])));

在我的机器上,使用时和 set_default_verify_paths()则不会调用,我得到以下的输出:

$ ./a.out www.google.co.uk /?gws_rd = SSL
验证:/ C = US / O = GeoTrust的Inc./CN=GeoTrust全球CA
验证:0
例外:握手:证书验证失败

set_default_verify_paths()调用:

$ ./a.out www.google.co.uk /?gws_rd = SSL
验证:/ C = US / O =的Equifax / OU =安全的Equifax证书颁发机构
验证:1
验证:/ C = US / O = GeoTrust的Inc./CN=GeoTrust全球CA
验证:1
验证:/ C = US / O =谷歌公司/ CN =谷歌的互联网机构G2
验证:1
验证:/ C = US / ST =加州/ L =山景/ O =谷歌公司/ CN = google.com
验证:1

rfc2818_verification(host.name)时:

$ ./a.out www.google.co.uk /?gws_rd = SSL
验证:/ C = US / O =的Equifax / OU =安全的Equifax证书颁发机构
验证:1
验证:/ C = US / O = GeoTrust的Inc./CN=GeoTrust全球CA
验证:1
验证:/ C = US / O =谷歌公司/ CN =谷歌的互联网机构G2
验证:1
验证:/ C = US / ST =加州/ L =山景/ O =谷歌公司/ CN = google.com
验证:0
例外:握手:证书验证失败

Hello I'm trying to download content from webpage that uses https via C++. My very basic client program taken from the Boost asio examples compiles and runs fine, but when I test it eg with Google: www.google.co.uk/?gws_rd=ssl, it gives me the error "handshake: certificate verify failed".

I think this is because ctx.set_default_verify_paths() doesn't contain a path with a certificate for Google (I'm on Windows).

I'm very new to SSL, please can you help me with the following questions:

1) When I installed openSSL, did it stick a list of trusted certifying authorities on my computer? If it did, what would cause Google's certificate not to be verified?

2) Is there anyway of saying I don't care about verification, proceed to connect anyway, like when you add an exception manually in firefox? I'm not particularly interested in whether the connection is trusted as I am not transmitting anything that needs to be secure.

Answers to either would be greatly appreciated!

#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <string>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

using boost::asio::ip::tcp;
namespace ssl = boost::asio::ssl;
typedef ssl::stream<tcp::socket> ssl_socket;

int main(int argc, char* argv[])
{
  try
  {
if (argc != 3)
{
  std::cout << argc;
  std::cout << "Usage: sync_client <server> <path>\n";
  std::cout << "Example:\n";
  std::cout << "  sync_client www.boost.org /LICENSE_1_0.txt\n";
  return 1;
}

boost::asio::io_service io_service;

// Create a context that uses the default paths for
// finding CA certificates.
ssl::context ctx(ssl::context::sslv23);
ctx.set_default_verify_paths();

// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(argv[1], "https");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

// Try each endpoint until we successfully establish a connection.
ssl_socket socket(io_service, ctx);
boost::asio::connect(socket.lowest_layer(), endpoint_iterator);
socket.lowest_layer().set_option(tcp::no_delay(true));

// Perform SSL handshake and verify the remote host's
// certificate.
socket.set_verify_mode(ssl::verify_peer);
socket.set_verify_callback(ssl::rfc2818_verification("host.name"));
socket.handshake(ssl_socket::client);

// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << argv[2] << " HTTP/1.0\r\n";
request_stream << "Host: " << argv[1] << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";

// Send the request.
boost::asio::write(socket, request);

// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");

// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);

if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
  std::cout << "Invalid response\n";
  return 1;
}
if (status_code != 200)
{
    std::cout << "Response returned with status code " << status_code << "\n";
    std::cout << status_message << "\n";
    // Read the response headers, which are terminated by a blank line.
    boost::asio::read_until(socket, response, "\r\n\r\n");

    // Process the response headers.
    std::string header;
    while (std::getline(response_stream, header) && header != "\r")
        std::cout << header << "\n";
    std::cout << "\n";
      return 1;
}
//code to read the data goes here, which works fine for http pages    
  }
  catch (std::exception& e)
  {
    std::cout << "Exception: " << e.what() << "\n";
  }
  return 0;
}

解决方案

Most OpenSSL installations will install trusted certificates as part of the installation process, and boost::asio::ssl::context::set_default_verify_paths() is fairly good at finding the correct paths.

The certification verification is failing because the the client is attempting to verify the peer's certificates with hostname verification (rfc2818), and is checking for the literal "host.name" to be in the certificate, and the server's certificates do not list "host.name" as a name. Try changing:

socket.set_verify_callback(ssl::rfc2818_verification("host.name"));

to:

socket.set_verify_callback(ssl::rfc2818_verification(argv[1]));


To disable peer verification, provide boost::asio::ssl::verify_none to the boost::asio::ssl::stream::set_verify_mode():

socket.set_verify_mode(boost::asio::ssl::verify_none);

Boost.Asio provides other peer verify_modes.


When peer verification is failing, it can be helpful to provide a custom callback to boost::asio::ssl::stream::set_verify_callback that provides diagnostic information. As noted in the documentation, the handler signature must be:

bool verify_callback(
  bool preverified, // True if the certificate passed pre-verification.
  verify_context& ctx // The peer certificate and other context.
);

Here is a custom functor that prints the certificate subject name:

///@brief Helper class that prints the current certificate's subject
///       name and the verification results.
template <typename Verifier>
class verbose_verification
{
public:
  verbose_verification(Verifier verifier)
    : verifier_(verifier)
  {}

  bool operator()(
    bool preverified,
    boost::asio::ssl::verify_context& ctx
  )
  {
    char subject_name[256];
    X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
    X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
    bool verified = verifier_(preverified, ctx);
    std::cout << "Verifying: " << subject_name << "\n"
                 "Verified: " << verified << std::endl;
    return verified;
  }
private:
  Verifier verifier_;
};

///@brief Auxiliary function to make verbose_verification objects.
template <typename Verifier>
verbose_verification<Verifier>
make_verbose_verification(Verifier verifier)
{
  return verbose_verification<Verifier>(verifier);
}

And its usage:

socket.set_verify_callback(make_verbose_verification(
  boost::asio::ssl::rfc2818_verification(argv[1])));

On my machine, when using it and set_default_verify_paths() is not invoked, I get the following output:

$ ./a.out www.google.co.uk /?gws_rd=ssl
Verifying: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
Verified: 0
Exception: handshake: certificate verify failed

And when set_default_verify_paths() is invoked:

$ ./a.out www.google.co.uk /?gws_rd=ssl
Verifying: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
Verified: 1
Verifying: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
Verified: 1
Verifying: /C=US/O=Google Inc/CN=Google Internet Authority G2
Verified: 1
Verifying: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=google.com
Verified: 1

And when rfc2818_verification("host.name") is used:

$ ./a.out www.google.co.uk /?gws_rd=ssl
Verifying: /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
Verified: 1
Verifying: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
Verified: 1
Verifying: /C=US/O=Google Inc/CN=Google Internet Authority G2
Verified: 1
Verifying: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=google.com
Verified: 0
Exception: handshake: certificate verify failed

这篇关于SSL证书和Boost ASIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆