The smallest minimal example of an HTTPS GET request with openssl

Viktor Dukhovni openssl-users at dukhovni.org
Sat Mar 30 19:59:21 UTC 2019


On Sat, Mar 30, 2019 at 08:09:01PM +0100, Ivan Medoedov wrote:

> You are right of course. I handle HTTP myself. A TLS connection example
> will suffice.
> 
> > > https://wiki.openssl.org/index.php/SSL/TLS_Client

That example can be simplified, but OpenSSL does not presently
provide a built-in high-level function to make a verified connection
to a given host:port.

With library initialization now implicit in 1.1.0 and later, and
thread-safety no longer requiring application callbacks, this would
now be easier to provide, but:

    * SSL_CTX creation is moderately expensive, and one should
      generally create and use the same SSL_CTX for multiple SSL
      connecitons in any applications that uses more than one SSL
      connection.  So typically, there would still be a one-time
      initialization step to create the SSL_CTX (application context).

    * Some applications will want to do post-handshake I/O via the
      socket API, and prefer to hand OpenSSL an already connected
      socket on which to perform the TLS handshake.  Others may
      want OpenSSL to establish the connection and may prefer to
      use BIO interface to interact with the peer.

    * While many systems have a usable default "trust store",
      some do not, or the default "trust store" is overly inclusive.
      Applications should generally allow the user to specify the
      set of trusted CAs.

    ...

Through in enough similar qualifiers, and you end up with the rather
complex example.  It could perhaps be refactored as (hypothetical
interface):

	/*
	 * Context with default trust store, protocols, ciphers, ...
	 * and peer verification enabled.
	 */
	SSL_CTX *app_ctx = SSL_default_ssl_ctx(TLS_method());

	/*
	 * Prepare verified (with name checks) SSL handle for the
	 * requested host:port (with SNI).
	 */
	SSL *con = SSL_default_ssl(app_ctx, host, port);

Then depending on whether you want to give OpenSSL an already
connected socket, or have OpenSSL make the connection for you:

	int err = SSL_connect_socket(con, fd);

or (something along the lines of):

	BIO *bp = SSL_connect_hostport(con, host, port, &err);

At this point a stock error handler may be required, but if all
went well, you now need an I/O loop.  And so would need to either
use the connected file descriptor with your own buffering, ...
or use OpenSSL BIOs, or some other buffering I/O layer that
supports custom read/write wrappers.

On FreeBSD/NetBSD it might be nice to have stock "fittings" to
wrap stdio around OpenSSL connections via:

     #include <stdio.h>

     FILE *
     funopen(const void *cookie,
             int	(*readfn)  (void *, char *, int),
             int	(*writefn) (void *, const char *, int),
             fpos_t	(*seekfn)  (void *, fpos_t, int),
             int	(*closefn) (void *));

Providing higher level interfaces to the core TLS library would
make a good project for someone good at API design, who is familiar
with OpenSSL, but more interested in the API than the internals.

-- 
	Viktor.


More information about the openssl-users mailing list