I have a state machine with the following states: create, connect, send, receive.
When the state sequence is the following: create, connect, send, receive everything is ok (with my code, sent in the previous email). However when there is a receive code after connect there is a problem. There is no data after this receive phase (maybe is not problem) but after that: send executed successfully and the receive returns with no data.
create
connect
receive : no data, maybe ok
send: ok
receive : no data here !!
create: calls CreateSSL
connect: calls ConnectSSL
send: calls SendSSL
receive: calls ReceiveSSL
What may the problem?
Attila
On Mon, Jun 22, 2020 at 7:35 PM Viktor Dukhovni <openssl-users@xxxxxxxxxxxx> wrote:
On Mon, Jun 22, 2020 at 03:17:41PM +0200, Attila Csosz wrote:
> char HEADERS[] = "GET /search?q=arduino HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
> char HOST_NAME_PORT[] = "www.google.com:443";
Note the "Connection: close" in the HTTP request header!
> void init_openssl()
> {
> SSL_load_error_strings();
> SSL_library_init();
> }
>
> void CreateSSL()
> {
> // Create SSL context
> meth = SSLv23_client_method();
> if (!meth) throw Exception("SSL: method");
>
> ctx = SSL_CTX_new(meth);
> if (!ctx) throw Exception("SSL: SSL_CTX_new");
> old_opts = SSL_CTX_set_options(ctx, SSL_OP_ALL);
The SSL_CTX need only be created once, not once per connection.
You've made no provision for verifying the server certificate.
Typically you would load trusted CA certificate locations into
the SSL_CTX.
> web = BIO_new_ssl_connect(ctx);
> if (!web) throw Exception("SSL: BIO_new_ssl_connect");
> }
This code belows in the ConnectSSL function.
>
> void ConnectSSL()
> {
> // Connect
> res = BIO_set_conn_hostname(web, HOST_NAME_PORT);
> if (!res) throw Exception("SSL: BIO_ctrl");
>
> res = BIO_get_ssl(web, &ssl);
> if (!res) throw Exception("SSL: BIO_ctrl");
>
> res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
> if (!res) throw Exception("SSL: SSL_set_cipher_list");
>
> res = BIO_do_connect(web);
> if (res <= 0) throw Exception("SSL: BIO_do_connect");
>
> res = BIO_do_handshake(web);
> if (res <= 0) throw Exception("SSL: BIO_do_handshake");
This connection is unauthenticated. Perhaps that's OK, but often it is
not.
> }
>
> void SendSSL()
> {
> // Send
> err = BIO_puts(web, HEADERS);
> if (err <= 0) throw Exception("SSL: BIO_puts");
> }
>
> void ReceiveSSL()
> {
> // Read
> sResult = "";
> for (;;) {
> len = BIO_read(web, buf, sizeof(buf));
> sResult += buf;
> if (len <= 0)
> break;
> }
The server closes the connection after returning its reply.
You need to close the SSL BIO to avoid a memory leak.
> ---------
> It is ok for one request.
>
> My problem when I trying to send a new search request to google it works
> only when I call
> CreateSSL();
> ConnectSSL();
> again
Naturally, you're not doing HTTP/1.1 connection keep-alive, and in any
case would need to be prepared for the server to close the connection
now and then. You need an actual HTTPS library, naive open-coding of an
HTTP client over SSL is unlikely to be correct. Something like libcurl
or similar is the way to go.
> What may the problem?
You're writing a naïve HTTPS client from scratch. A correct
implementation would understand "Content-Length" and chunked
trasfer encoding, handle server-initiated disconnects, be
prepared to receive multi-record responses, ...
--
Viktor.