Skip to content

Commit

Permalink
HTTPS client with peer verification; resolved #41.
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-crowhurst committed Dec 31, 2015
1 parent b6d67d5 commit 3a0802d
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ CMakeLists.txt text
*.bat eol=crlf

# Denote all files that are truly binary and should not be modified.
*.pem binary
*.a binary
*.so binary
*.dll binary
*.dylib binary
*.lib binary
*.lib binary
8 changes: 8 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,20 @@ if ( BUILD_SSL )

add_executable( https_client_verify_none https_client/source/verify_none.cpp )
target_link_libraries( https_client_verify_none ${CMAKE_PROJECT_NAME} )

add_executable( https_client_verify_peer https_client/source/verify_peer.cpp )
target_link_libraries( https_client_verify_peer ${CMAKE_PROJECT_NAME} )
endif ( )

#
# Install
#
install( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example" DESTINATION ${CMAKE_INSTALL_PREFIX} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE )

install( DIRECTORY "${CMAKE_SOURCE_DIR}/example/https_client/resource/certificates" DESTINATION "${CMAKE_INSTALL_PREFIX}/resource" FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE )

install( FILES "${CMAKE_SOURCE_DIR}/example/serving_html/resource/index.html" DESTINATION "resource" )
install( FILES "${CMAKE_SOURCE_DIR}/example/compression/resource/data.zlib" DESTINATION "resource" )
install( FILES "${CMAKE_SOURCE_DIR}/example/transfer_encoding_request/resource/request.txt" DESTINATION "resource" )


1 change: 1 addition & 0 deletions example/https_client/resource/certificates/578d5c04.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
-----END CERTIFICATE-----
72 changes: 72 additions & 0 deletions example/https_client/source/verify_peer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Example illustrating a HTTPS client with peer verification.
*
* Get CA certifiate (http://gagravarr.org/writing/openssl-certs/general.shtml)
* note the subject hash never seems to match?!? use dtruss/strace to see what it wants to load. Its also more reliable
* to download the certificate straight from the CA (for google.com its https://www.geotrust.com/resources/root-certificates/)
*
* http://stackoverflow.com/questions/23343910/verify-errornum-20-when-connecting-to-gateway-sandbox-push-apple-com
* 1. openssl s_client -connect www.google.com:443 -showcerts
* 2. download root CA
* 3. test root CA, openssl s_client -connect www.google.com:443 -showcerts -CAfile ./certs/Equifax_Secure_Certificate_Authority.pem
* Each file in the directory must contain a single certificate.
* The files must be named using the subject name's hash and an extension of ".0".
* 4. openssl x509 -in certs/Equifax_Secure_Certificate_Authority.pem -noout -subject_hash (also see c_rehash)
* can be used to generate the subject name hash(e.g. e5d93f80). Just append ".0" to this value and create a softlink with this name(e5d93f80.0) to the CA file. If there are more than one CA files with same the subject name hash value, their extensions should be different(e.g. e5d93f80.1). The search is performed in the ordering of the extension number.
* opensssl has introduced this technique to reduce the the CA file look up time. Otherwise openssl may have to read all files in the CApath to find the matching CA file.
* 5. ln -s Equifax_Secure_Certificate_Authority.pem 594f1775.0
* 6. verify its all setup correct, openssl s_client -showcerts -CApath ./certs -connect google.com:443
* 7. make sure the file permissions are correct for the CA root cert (http://stackoverflow.com/questions/15936668/boostasiosslcontextadd-verify-path)
*
* to confirm loading of the right hash use strace or dtruss (on mac) to verifiy the hash file being loaded.
* Usage:
* ./distribution/example/https_client_verify_peer
*/

#include <memory>
#include <cstdio>
#include <cstdlib>
#include <restbed>

using namespace std;
using namespace restbed;

int main( const int, const char** )
{
auto request = make_shared< Request >( Uri( "https://www.google.com" ) );
request->set_header( "Accept", "*/*" );
request->set_header( "Host", "www.google.com" );
request->set_query_parameter( "query", "search term" );

auto settings = make_shared< SSLSettings >( );
settings->set_certificate_authority_pool( Uri( "file://distribution/resource/certificates", Uri::Relative ) );

auto response = Http::sync( request, settings );

fprintf( stderr, "*** Response ***\n" );
fprintf( stderr, "Status Code: %i\n", response->get_status_code( ) );
fprintf( stderr, "Status Message: %s\n", response->get_status_message( ).data( ) );
fprintf( stderr, "HTTP Version: %.1f\n", response->get_version( ) );
fprintf( stderr, "HTTP Protocol: %s\n", response->get_protocol( ).data( ) );

for ( const auto header : response->get_headers( ) )
{
fprintf( stderr, "Header '%s' > '%s'\n", header.first.data( ), header.second.data( ) );
}

if ( response->has_header( "Transfer-Encoding" ) )
{
Http::fetch( "\r\n", response );
}
else
{
auto length = 0;
response->get_header( "Content-Length", length );

Http::fetch( length, response );
}

fprintf( stderr, "Body: %.*s...\n", 3, response->get_body( ).data( ) );

return EXIT_SUCCESS;
}
2 changes: 2 additions & 0 deletions source/corvusoft/restbed/uri.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ namespace restbed
//Friends

//Definitions
static const bool Relative = true;
static const bool Absolute = false;

//Constructors
explicit Uri( const std::string& value, bool relative = false );
Expand Down

0 comments on commit 3a0802d

Please sign in to comment.