Newer
Older
#include "HTTPSRequest.h"
#include <errno.h>
#include <iostream>
#include <string.h>
// PolarSSL internal state
mbedtls_net_context server_fd;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
HTTPSRequest::HTTPSRequest(const std::shared_ptr<URL> u) {
if (!initTLS())
{
printf("failed to start TLS!");
return;
}
uri = u;
version = Version::HTTP10;
method = Method::GET;
userAgent = "NetRunner/0.1 PolarSSL/2.5.1";
}
bool HTTPSRequest::sendRequest(std::function<void(const HTTPResponse&)> responseCallback) const {
std::string response;
std::string document = uri->path;
std::string host = uri->host;
std::string port = std::to_string(uri->port);
int ret;
unsigned flags;
if(mbedtls_net_connect(&server_fd, host.c_str(),port.c_str(), MBEDTLS_NET_PROTO_TCP) != 0 )
{
return false;
}
if (mbedtls_ssl_config_defaults(&conf,MBEDTLS_SSL_IS_CLIENT,MBEDTLS_SSL_TRANSPORT_STREAM,MBEDTLS_SSL_PRESET_DEFAULT) != 0)
{
return false;
}
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
mbedtls_ssl_conf_ca_chain( &conf, &cacert, nullptr );
if( mbedtls_ssl_setup( &ssl, &conf ) != 0 )
{
return false;
}
if(mbedtls_ssl_set_hostname( &ssl, uri->host.c_str() ) != 0 )
{
return false;
}
mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, nullptr );
int state = mbedtls_ssl_handshake( &ssl );
while(state != 0)
{
if( state != MBEDTLS_ERR_SSL_WANT_READ && state != MBEDTLS_ERR_SSL_WANT_WRITE )
{
printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -state );
return false;
}
}
if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )
{
printf("Invalid server cert!");
return false;
}
const std::string request = methodToString(method) + std::string(" ") + document + std::string(" ") + versionToString(version) + std::string("\r\nHost: ") + host + std::string("\r\nUser-Agent: ") + userAgent + std::string("\r\n\r\n");
while( ( state = mbedtls_ssl_write( &ssl, reinterpret_cast<const unsigned char*>(request.c_str()), request.length() ) ) <= 0 )
{
if( state != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", state );
return false;
}
}
do
{
ret = mbedtls_ssl_read( &ssl, reinterpret_cast<unsigned char *>(buffer), 512 );
if (ret <= 0)
break;
else
response += std::string(buffer, static_cast<unsigned int>(ret));
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
}
while( ret != 0 );
// clean up after the request
mbedtls_ssl_close_notify( &ssl );
responseCallback(HTTPResponse(response));
mbedtls_net_free( &server_fd );
mbedtls_x509_crt_free( &cacert );
mbedtls_ssl_free( &ssl );
mbedtls_ssl_config_free( &conf );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
return true;
}
const std::string HTTPSRequest::versionToString(const Version ver) const {
switch (ver) {
case Version::HTTP10:
return "HTTP/1.0";
default:
return "ERROR";
}
}
const std::string HTTPSRequest::methodToString(const Method meth) const {
switch (meth) {
case Method::GET:
return "GET";
case Method::POST:
return "POST";
default:
return "ERROR";
}
}
bool HTTPSRequest::initTLS()
{
mbedtls_net_init( &server_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
mbedtls_x509_crt_init( &cacert );
mbedtls_ctr_drbg_init( &ctr_drbg );
const char *seed = "netrunner_ssl_seed$%?rvx86_despair^^%$#@";
mbedtls_entropy_init( &entropy );
if(mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, reinterpret_cast<const unsigned char*>(seed), strlen(seed) ) != 0 )
{
return false;
}
int ret = mbedtls_x509_crt_parse_file( &cacert, "ca-bundle.crt");
if( ret < 0 )
{
printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
return false;
}
return true;