snippetcMinor
Complete async OpenSSL example
Viewed 0 times
asyncexamplecompleteopenssl
Problem
I am trying to create a fully async example of a client and server using SSL.
I think these are the required assumptions:
Are there any others?
On the accepting side, how can I tell if the socket is ready for a call to
Here is an example that seems to work completely. Please tell me if anything is wrong with it.
`#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef enum {
CONTINUE,
BREAK,
NEITHER
} ACTION;
ACTION ssl_connect(SSL ssl, int wants_tcp_write, int* connecting) {
printf("calling SSL_connect\n");
int result = SSL_connect(ssl);
if (result == 0) {
long error = ERR_get_error();
const char* error_str = ERR_error_string(error, NULL);
printf("could not SSL_connect: %s\n", error_str);
return BREAK;
} else if (result
I think these are the required assumptions:
- Connecting may require socket readability and writeability notifications.
- When the socket is readable,
SSL_writemay need to be called depending on the result of the last call toSSL_write.
- When the socket is writable,
SSL_readmay need to be called depending on the result of the last call toSSL_read.
- If the last call to
SSL_connect,SSL_write, orSLL_readreturnedSSL_ERROR_WANT_WRITE, then the application cannot write anything new withSSL_writeuntil the last call is recalled.
- On the connecting side,
SSL_writecannot be called untilSSL_connectsucceeds.
Are there any others?
On the accepting side, how can I tell if the socket is ready for a call to
SSL_write?Here is an example that seems to work completely. Please tell me if anything is wrong with it.
- It can be compiled with
gcc ssl.c -lssl -lcrypto.
- The client is run with
./a.out client.
- The server is run with
./a.out server.
- You can make a sample pem for use by the server with:
echo -e "\n\n\n\n\n\n" | /usr/bin/openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout cert.pem -out cert.pem -config openssl.cnf
openssl x509 -in cert.pem -outform DER -out cert.pem.crt
`#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef enum {
CONTINUE,
BREAK,
NEITHER
} ACTION;
ACTION ssl_connect(SSL ssl, int wants_tcp_write, int* connecting) {
printf("calling SSL_connect\n");
int result = SSL_connect(ssl);
if (result == 0) {
long error = ERR_get_error();
const char* error_str = ERR_error_string(error, NULL);
printf("could not SSL_connect: %s\n", error_str);
return BREAK;
} else if (result
Solution
In terms of error handling, it seems to be much safer to call
Basically, each thread shares an error stack. While
ERR_clear_error() before any call to SSL_read(), SSL_write(), SSL_accept, and so on. See one of the few reported cases where error management has messed up people.Basically, each thread shares an error stack. While
SSL_get_error() grab the latest error associated to a ssl session, it does not remove it. ERR_get_error does. You might be in a case where you are reading an error from a previous call. This API is really... dubious, for the least.Context
StackExchange Code Review Q#108600, answer score: 3
Revisions (0)
No revisions yet.