Ciao Sto cercando di scaricare il contenuto da una pagina web che utilizza https via C++. Il mio programma client di base preso dagli esempi di Boost asio viene compilato e funziona bene, ma quando lo collaudo ad esempio con Google: www.google.co.uk/?gws_rd=ssl, mi dà l'errore "handshake: certificate certificate failed" .Certificati SSL e Boost asio
Penso che questo sia dovuto al fatto che ctx.set_default_verify_paths() non contiene un percorso con un certificato per Google (sono su Windows).
sto molto di nuovo da SSL, per favore potete aiutarmi con le seguenti domande:
1) Quando ho installato OpenSSL, vero bastone un elenco di autorità di certificazione di fiducia sul mio computer? In caso affermativo, cosa causerebbe la mancata verifica del certificato di Google?
2) C'è comunque da dire che non mi interessa la verifica, procedere comunque alla connessione, come quando si aggiunge manualmente un'eccezione in firefox? Non sono particolarmente interessato a sapere se la connessione è affidabile poiché non sto trasmettendo nulla che debba essere sicuro.
Le risposte a entrambi sarebbero molto apprezzate!
#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;
}
Ciao vi ringrazio molto per il vostro aiuto. Quando ho messo in funzione diagnostica ottengo la prima uscita che trovate: 'Verifica:/C = US/O = GeoTrust Inc./CN=GeoTrust globale CA Verificati: 0 Eccezione: la stretta di mano: certificato di verifica failed' ... dopo aver rimosso l'errore "host.name". Ho ragione nel pensare che questo indichi che set_default_verify_paths() non sta facendo un ottimo lavoro? ... Quando faccio 'socket.set_verify_mode (boost :: asio :: :: SSL verify_none);' ottengo un'eccezione lettura breve che credo sia un problema di non correlato. Grazie ancora per il vostro aiuto – Jez
@Jez E 'possibile che l'installazione non ha incluso certificati attendibili, il percorso è non essere trovato tramite 'set_default_verify_paths()', oppure l'applicazione non dispone delle autorizzazioni per leggere dalla directory. Consultare la documentazione dell'installatore o sfogliare il file system. Se si trova un percorso contenente i certificati, aggiungere che il percorso al contesto tramite [ 'add_verify_path()'] (http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/ssl__context/ add_verify_path/overload1.html). –
Si scopre che non avevo i certificati installati come parte di OpenSSL. Ho in mano la lista dei certificati di Mozilla in un unico file PEM, ma quando ho drill-down in quanto 'add_verify_path()' [in realtà è un wrapper per] (https://www.openssl.org/docs/ssl/ SSL_CTX_load_verify_locations.html), sembra che ogni certificato sia necessario in un file separato e l'estensione di questi file deve essere .0 non .pem. E 'corretto e se sì, come faccio a prendere il mio singolo file PEM e dividerlo? Cheers – Jez