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