You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

143 lines
4.5 KiB

// ©2008-2017 despair <despair@netrunner.cc>
#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);
char buffer[512];
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));
}
}
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;
}