repetitive ssl send

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

repetitive ssl send

Attila Csosz
Hi,

I've a small C code and I can send and receive from google.
Here is the code

---------
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";
const char* PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS";

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);

 web = BIO_new_ssl_connect(ctx);
 if (!web) throw Exception("SSL: BIO_new_ssl_connect");
}

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");
}

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;
 }
}

void TestProc()
{
 init_openssl();

 CreateSSL();
 ConnectSSL();
 SendSSL();
 ReceiveSSL();

 // Next request
 //

 lTmp = new TStringList;
 lTmp->Add(sResult);
 lTmp->SaveToFile("c:\\temp\\a1.htm");

 // Free
 BIO_free_all(web);
 EVP_cleanup();

}

---------
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

so my new search request is 
 CreateSSL();
 ConnectSSL();
 SendSSL();
 ReceiveSSL();

Is this normal?

When I trying to use
 SendSSL();
 ReceiveSSL();
only
I have got a page with errors (I think). The response is shorter, starts with 0 (not with HTTP/1.1 200 OK)

What may the problem?


Thanks for your help


Reply | Threaded
Open this post in threaded view
|

Re: repetitive ssl send

Viktor Dukhovni
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.
Reply | Threaded
Open this post in threaded view
|

Re: repetitive ssl send

Attila Csosz
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 <[hidden email]> 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.