I want to write a simple application, which grabs the content of the HTTPS page: https://httpbin.org/html.
I know how to access its insecure (HTTP) version (http://httpbin.org/html), I just need to send a request using sockets:
std::stringstream ss;
ss << "GET /html HTTP/1.1" << "\r\n"
<< "Host: httpbin.org\r\n"
<< "Connection: close"
<< "\r\n\r\n";
std::string request = ss.str();
// socket creation, connect
send(sock, request.c_str(), request.size(), 0);
And it works. However, when using secure sockets (#include <openssl/ssl.h>
) I got the following error: error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error
when trying result = SSL_connect(ssl);
Here's the code:
#include <sys/stat.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <iostream>
#include <sstream>
int main(int argc, char **argv)
{
int sock;
char buff[1024];
struct sockaddr_in address;
struct hostent *host = NULL;
std::string servername = "httpbin.org";
if (!inet_aton(servername.c_str(), &address.sin_addr))
if (host = gethostbyname(servername.c_str()))
address.sin_addr = *(struct in_addr*)host->h_addr;
else
return -1;
address.sin_port = htons(443);
address.sin_family = AF_INET;
std::stringstream ss;
ss << "GET /html HTTP/1.1" << "\r\n"
<< "Host: httpbin.org\r\n"
<< "Connection: close"
<< "\r\n\r\n";
std::string request = ss.str();
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) != -1)
{
if (connect(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) != -1)
{
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_method());
if (!ctx)
return -1;
int result = -1;
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
result = SSL_connect(ssl);
if (result == 0)
{
long error = ERR_get_error();
const char* error_str = ERR_error_string(error, NULL);
printf("%s\n", error_str);
return 0;
}
SSL_write(ssl, request.c_str(), request.size());
SSL_read(ssl, buff, 1024);
printf("%s\n", buff);
memset(buff, 0, 1024);
SSL_free(ssl);
SSL_CTX_free(ctx);
close(sock);
}
}
return 0;
}
...
SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error
when tryingresult = SSL_connect(ssl);
This means that the server sends a TLSv1 alert back probably because it does not like the information send by the client in the handshake (ClientHello). This might be because the client only offers ciphers which the server does not supports, that the client uses a protocol version not supported or very often also because the server requires the TLS SNI extension to determine which certificate to provide to the client. Testing with other tools indicates that this is actually the case. The problem thus can be solved in your code by using the SNI extension:
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, sock);
// ADD THIS
SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)servername.c_str());
result = SSL_connect(ssl);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With