0

I'm trying to connect to my website with OpenSSL for C++ and this is what I have:

#include "openssl/ssl.h"
#include "openssl/bio.h"
#include "openssl/err.h"

#include <string>

int main( )
{
    BIO * bio;
    int p;

    char * request = (char*)"GET / HTTPS/1.1\x0D\x0AHost: (website)/auth.php\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";
    char r[ 1024 ];

    ERR_load_BIO_strings( );
    SSL_load_error_strings( );
    OpenSSL_add_all_algorithms( );

    bio = BIO_new_connect( "(website):80" );
    if ( bio == NULL )
    {
        printf( "BIO is null\n" ); return 0;
    }

    if ( BIO_do_connect( bio ) <= 0 )
    {
        ERR_print_errors_fp( stderr );
        BIO_free_all( bio );
        return 0;
    }

    BIO_write( bio, request, strlen( request ) );    

    while(true)
    {
        p = BIO_read( bio, r, 1023 );
        if ( p <= 0 ) break;
        r[ p ] = 0;
        printf( "%s", r );
    }

    BIO_free_all( bio );
    system( "pause" );
    return 0;
}

When I run this, I get this error:

HTTP/1.0 400 Bad request
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>
Press any key to continue . . .

The website has an ssl certificate and whenever I try to connect to the main site it says that it has been moved to the same domain but with an https:// instead of http:// in front.

Where I enter my website I have it with www in front and of course the tld after. As you can see I'm trying to read from a PHP script so if anyone knows how I can fix this I'd appreciate it.

jww
  • 97,681
  • 90
  • 411
  • 885
  • 2
    Please don't cast the literal setting `request` to `(char*)`, use `const char* request = "..."`. – Galik Feb 17 '18 at 23:39
  • 2
    Are you working from a tutorial or an example? I seem to remember you have to open a normal TCP socket before starting the `SSL` part. – Galik Feb 17 '18 at 23:51
  • 4
    The protocol specifier in an `HTTP` `GET` request is always `HTTP/x.y`. The fact that, supposedly, the connection is encrypted doesn't change that. The actual protocol is still "HTTP/1.0", or "HTTP/1.1", and not "HTTPS/x.y". This may or may not be the only problem with the shown code. – Sam Varshavchik Feb 18 '18 at 00:49
  • @SamVarshavchik: I bet that's it. – Lightness Races in Orbit Feb 18 '18 at 01:02
  • 1
    Yep, HTTPS is HTTP over SSL/TLS, so the header should be HTTP (just to provide some background). – Maarten Bodewes Feb 18 '18 at 01:42

1 Answers1

3

char * request = (char*)"GET / HTTPS/1.1\x0D\x0AHost: (website)/auth.php\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";

Change to:

const char request[] = "GET /auth.php HTTP/1.1\r\n"
    "Host: www.example.com\r\n"
    "Connection: Close\r\n\r\n";

(Thanks to Sam Varshavchik and Lightness Races in Orbit for catching HTTPS/1.1).


bio = BIO_new_connect( "(website):80" );

Change to:

bio = BIO_new_connect( "www.example.com:443" );

You might also be interested in SSL/TLS Client on the OpenSSL wiki. You seem to be missing stuff I expect to see, like SSL_CTX_new, BIO_set_conn_hostname, SSL_set_tlsext_host_name, BIO_do_handshake and several others.

In the future, please stop redacting important information, like (website). No one can duplicate your problem with missing information.

C++ can make it easier to use OpenSSL. You can avoid explicit calls to functions like EVP_CIPHER_CTX_free by using unique_ptr. For some C++ examples, see EVP Symmetric Encryption and Decryption | C++ Programs on the OpenSSL wiki, unique_ptr and OpenSSL's STACK_OF(X509)*, How to get PKCS7_sign result into a char * or std::string, etc.

jww
  • 97,681
  • 90
  • 411
  • 885