Securing the socket
--#--
OpenSSL uses two central structures for opening and managing
secure connections -- SSL_ctx and SSL. SSL_ctx is a context
object. It holds a list of ciphers, CA certificates for authenticating
the server, client-side certificates, protocol specifiers, validation
routines and other things that determine how secure the connection will
be. In this example, we won't do a lot with it, but will rely on most
of the OpenSSL defaults.
SSL is a central structure to the program. Once the connection is
established, SSL holds pointers to practically everything -- including
the SSL_ctx. That said, you don't really need to worry much about it,
except to remember to keep tossing the SSL struct around to any of the
business functions.
Let's start by initializing the two structures:
#include
SSL *ssl = NULL;
SSL_CTX *ssl_ctx = NULL;
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
ssl = SSL_new(ssl_ctx);
Not hard, was it? The only parameter we pass to the SSL_CTX initializer
is a function pointer. In this case, we tell the context that we
want to use a client method that will attempt an SSL v3 connection,
but can fall back to SSL v2.
Now we need to define a function that will open a regular Internet socket
for HTTP transfers, and rig it up for SSL. Rename sockets.c ssl_sockets.c
and put this function there.
int SSLsocket(SSL *ssl, char *host, int port) {
int sock, result;
sock = openSocket(host, port);
SSL_set_fd(ssl, sock);
result = SSL_connect(ssl);
return result;
}
This function opens the socket just like Paul did, then associates the the
SSL struct with the socket. The next line, result = SSL_connect(ssl)
looks real simple, but a mountain of code runs as a result! This kicks off
the famous SSL handshake where both ends of the connection
exchange random bytes and agree on a key-exchange method and encryption
cipher. If this function returns -1, the connection failed. Otherwise,
we can use it.