s6-networking
Software
skarnet.org
The stls library interface
General information
libstls is a small support library for the
s6-tlsc and
s6-tlsd executables when they're built
against the LibreSSL
backend. You can use it in your own programs, but since
libtls
is already relatively high-level, it's probably not very useful.
Compiling
- Make sure the s6-networking headers, as well as the skalibs headers,
and the tls.h header, are visible in your header search path.
- Use #include <s6-networking/stls.h>
Linking
- Make sure the s6-networking libraries, as well as the skalibs
libraries, and the LibreSSL libraries, are visible in your library search path.
- Link against -lstls, -lskarnet, -ltls,
-lssl, -lcrypto,
`cat $sysdeps/socket.lib`, `cat $sysdeps/spawn.lib`, and
`cat $sysdeps/sysclock.lib`, where $sysdeps is your skalibs
sysdeps directory.
Programming
Utilities
void stls_drop ()
If the process is running as root, then this function drops its privileges
(else it does nothing).
The gid to drop to is read from the TLS_GID environment variable; the uid to
drop to is read from the TLS_UID environment variable. If those variables
are not given, then the uid, or gid, or both, are not changed. If they
contain something else than numerical uid/gids, the process exits 111 with
an error message.
Initializing the TLS engine
struct tls *stls_client_init_and_handshake (int const *fds, uint32_t preoptions, char const *servername)
This function initializes a TLS context for a client-side connection,
then performs a TLS handshake.
It then returns a non-null pointer to a struct tls context for the
application to pass to the stls_run function when it wants to
run the engine.
If the context cannot be initialized or the handshake cannot be performed,
the process exits (96 for configuration issues, 97 for context and handshake
issues) with an appropriate error message.
If the CADIR environment variable is set, then it must contain
the path of a directory containing the hashed names of the public
certificates identifying the trust anchors. Else, if the CAFILE
environment variable is set, then it must contain the path to a PEM file
containing all the certificates for the trust anchors. Else, the process
exits 100 with an error message.
The arguments are as follows:
- fds : an array of 4 file descriptors, that are in this
order: the fd reading from the application (cleartext), the fd writing to the
application (cleartext), the fd reading from the network, the fd writing to
the network.
- preoptions : a bitfield.
- Bit 0: if clear, no client authentication is performed. If set,
the CERTFILE and KEYFILE environment variables are read,
they must contain the path to a valid client certificate and private key
(else the process exits 96); this certificate is then provided to the
server for client authentication.
- servername : the server name used for SNI. If NULL, then
no SNI is performed, which may be a security risk.
struct tls *stls_server_init_and_handshake (int const *fds, uint32_t preoptions)
Same as the previous function, but on the server side. No servername
argument is required. The CERTFILE and KEYFILE environment
variables are mandatory, they point to the server's certificate and private
key. It is only necessary to set CADIR or CAFILE when bit
0 of preoptions is set, in which case client authentication will be
requested, and a list of trust anchors (read from either the directory
in CADIR or the PEM file in CAFILE) will be used to verify
the client certificate.
Running the TLS engine
void stls_run (struct tls *ctx, int *fds, unsigned int verbosity, uint32_t options, tain_t const *tto)
This function runs a full-duplex TLS/SSL engine, reading/writing
clear text from/to two file descriptors, and writing/reading
ciphertext to/from two other file descriptors, until the
connection is closed both ways (either with a SSL close, or
with EOF). It does not return.
- ctx is a pointer to a fully initialized context,
connected to fds[2] and fds[3]. The TLS
handshake must already be completed.
- fds is an array of 4 file descriptors, in this
order: fd reading clear text, fd writing clear text, fd reading
ciphertext, fd writing ciphertext.
- verbosity defines the engine's verbosity: the
higher the more verbose. This parameter is currently ignored.
- options is a bitfield.
- bit 0 tells the engine how to behave when
the local application closes the connection (i.e. when the engine
reads EOF on fds[0]). If the bit is clear, then the
engine will perform as SSL close: it will send a SSL close_notify,
and stop processing incoming records, waiting for a peer
acknowledgement of the close_notify. If the bit is set, then the
engine will not send a close_notify but simply transmit EOF to
the peer, while continuing to process incoming records until it
gets EOF back. close_notify is secure when handling protocols that
are not auto-terminated (such as HTTP 0.9), but it does not permit
separate closing of both ways. EOF allows full-duplex until the
very end, but is insecure if the application protocol does not
know in advance how many bytes it should get. Modern application
protocols should all work with EOF.
- tto is a pointer to a
tain_t
containing a relative time (i.e. a timeout). If *tto time elapses
with no application data being exchanged, the engine will forcibly close the
connection (with the method defined by options & 1).
You can use &tain_infinite_relative as a value for tto
if you don't want the engine to ever timeout.
stls_run will make the process die with an appropriate error
message and exit code if it encounters an unrecoverable error. If there were
no problems and the SSL/TLS connection closed cleanly, the process exits 0.