summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-11-22 00:16:06 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-11-22 00:16:06 +0000
commit47cbbb1619ace4013856843ef8f7d68279c74faa (patch)
tree351769a8bb3d202050c2f21a282cc0db26a58de8
parentfb76faf56aca9b79648d776896a4a4fae7c978cf (diff)
downloads6-networking-47cbbb1619ace4013856843ef8f7d68279c74faa.tar.xz
Add documentation, fix tiny privdrop bug
-rw-r--r--doc/index.html7
-rw-r--r--doc/libsbearssl/index.html131
-rw-r--r--doc/libstls/index.html112
-rw-r--r--doc/s6-tlsc-io.html217
-rw-r--r--doc/s6-tlsc.html197
-rw-r--r--doc/s6-tlsclient.html18
-rw-r--r--doc/s6-tlsd-io.html212
-rw-r--r--doc/s6-tlsd.html193
-rw-r--r--doc/s6-tlsserver.html11
-rw-r--r--doc/s6-ucspitlsc.html178
-rw-r--r--doc/s6-ucspitlsd.html168
-rw-r--r--doc/tls-overview.html142
-rw-r--r--src/sbearssl/sbearssl_drop.c4
-rw-r--r--src/stls/stls_drop.c4
14 files changed, 1199 insertions, 395 deletions
diff --git a/doc/index.html b/doc/index.html
index 049ed70..f402ab3 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -139,10 +139,15 @@ relevant page.
<h4> UCSPI tools for secure communication (TLS protocol) over TCP </h4>
<ul>
+<li> An <a href="tls-overview.html">overview</a> of the TLS-related programs </li>
<li><a href="s6-tlsclient.html">The <tt>s6-tlsclient</tt> program</a></li>
-<li><a href="s6-tlsserver.html">The <tt>s6-tlsserver</tt> program</a></li>
<li><a href="s6-tlsc.html">The <tt>s6-tlsc</tt> program</a></li>
+<li><a href="s6-tlsc-io.html">The <tt>s6-tlsc-io</tt> program</a></li>
+<li><a href="s6-ucspitlsc.html">The <tt>s6-ucspitlsc</tt> program</a></li>
+<li><a href="s6-tlsserver.html">The <tt>s6-tlsserver</tt> program</a></li>
<li><a href="s6-tlsd.html">The <tt>s6-tlsd</tt> program</a></li>
+<li><a href="s6-tlsd-io.html">The <tt>s6-tlsd-io</tt> program</a></li>
+<li><a href="s6-ucspitlsd.html">The <tt>s6-ucspitlsd</tt> program</a></li>
</ul>
<h4> TCP access control </h4>
diff --git a/doc/libsbearssl/index.html b/doc/libsbearssl/index.html
index 1579b2d..656c724 100644
--- a/doc/libsbearssl/index.html
+++ b/doc/libsbearssl/index.html
@@ -470,33 +470,44 @@ because *<em>t</em> does not represent a valid time.
i.e. a <tt>tai_t</tt> plus nanoseconds (which are simply ignored).
</p>
+<h4> <code> void sbearssl_drop () </code> </h4>
-<h3> Running the TLS/SSL engine (both clients and servers) </h3>
+<p>
+ 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.
+</p>
+
+<h3> Running the TLS/SSL engine (internal function for both clients and servers) </h3>
-<h4> <code> int sbearssl_run (br_ssl_engine_context *ctx, int *fds, pid_t pid, unsigned int verbosity, uint32_t options, tain_t const *tto) </code> </h4>
+<h4> <code> void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain_t const *tto, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, sbearssl_handshake_cb_context_t *cbarg) </code> </h4>
<p>
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) or a given subprocess dies.
+with EOF). It does not return.
</p>
<ul>
<li> <em>ctx</em> is a pointer to a fully initialized context,
connected to <em>fds</em>[2] and <em>fds</em>[3]. The
TLS/SSL handshake does not have to be completed. </li>
- <li> <em>fds</em> is an array of 5 file descriptors, in this
+ <li> <em>fds</em> is an array of 4 file descriptors, in this
order: fd reading clear text, fd writing clear text, fd reading
-ciphertext, fd writing ciphertext, selfpipe. </li>
- <li> <em>pid</em> is the pid of the application subprocess.
-When a SIGCHLD is detected on the selfpipe, the newly deceased
-process is reaped, and if it was <em>pid</em>, then the function
-returns as soon as it doesn't have anything left to write to
-the network peer. </li>
- <li> <em>verbosity</em> defines the engine's verbosity: the
-higher the more verbose. This parameter is currently ignored. </li>
+ciphertext, fd writing ciphertext. </li>
+ <li> <em>tto</em> is a pointer to a
+ <a href="//skarnet.org/software/skalibs/libstddjb/tai.html">tain_t</a>
+containing a relative time (i.e. a timeout) If *<em>tto</em> time elapses
+with no application data being exchanged, the engine will forcibly close the
+connection (with the method defined by <tt><em>options</em> &amp; 1</tt>).
+ You can use <tt>&amp;tain_infinite_relative</tt> as a value for <em>tto</em>
+if you don't want the engine to ever timeout. </li>
<li> <em>options</em> is a bitfield.
<ul>
<li> bit 0 tells the engine how to behave when
@@ -514,40 +525,94 @@ 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. </li>
</ul> </li>
- <li> <em>tto</em> is a pointer to a
- <a href="//skarnet.org/software/skalibs/libstddjb/tai.html">tain_t</a>
-containing a relative time (i.e. a timeout) If *<em>tto</em> time elapses
-with no application data being exchanged, the engine will forcibly close the
-connection (with the method defined by <tt><em>options</em> &amp; 1</tt>).
- You can use <tt>&amp;tain_infinite_relative</tt> as a value for <em>tto</em>
-if you don't want the engine to ever timeout. </li>
+ <li> <em>verbosity</em> defines the engine's verbosity: the
+higher the more verbose. This parameter is currently ignored. </li>
+ <li> <em>cb</em> is a pointer to a callback function that will be called
+once after the TLS handshake is performed. This function is called with
+two arguments: <em>ctx</em> (a pointer to the current bearssl context),
+and <em>cbarg</em> (a pointer to a caller-provided structure). </li>
+ <li> <em>cbarg</em> is a pointer to a structure provided by the caller.
+It will be passed as a second argument to <em>cb</em> when the TLS
+handshake has successfully completed. </li>
</ul>
<p>
<tt>sbearssl_run</tt> will make the process die with an appropriate error
message if it encounters an unrecoverable error. If there were no problems and the
-SSL/TLS connection closed cleanly, it returns -1. If the application
-subprocess dies early, <tt>sbearssl_run</tt> returns the <em>wstat</em>
-for that subprocess, i.e. the integer containing the information about
-its exit code or crash signal. No matter how <tt>sbearssl_run</tt> returns,
-the first four descriptors in <em>fds</em> are closed, but the
-selfpipe is untouched and the caller should free <em>ctx</em> itself.
+SSL/TLS connection closed cleanly, the process exits 0.
</p>
-<h4> <code> int sbearssl_s6tlsc (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity, char const *servername, int *sfd) </code> </h4>
+<h3> Initializing and running the engine </h3>
+
+<h4> <code> void sbearssl_client_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, char const *servername, sbearssl_handshake_cb_t_ref cb, unsigned int notif) </code> </h4>
+
+<p>
+ This function initializes a TLS context for a client-side connection,
+then runs the TLS engine via a call to <tt>sbearssl_run()</tt>. The
+function does not return.
+If the context cannot be initialized, the process exits 96 with an
+appropriate error message.
+</p>
+
+<p>
+ If the <tt>CADIR</tt> 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 <tt>CAFILE</tt>
+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.
+</p>
<p>
- This function implements <a href="../s6-tlsc.html">s6-tlsc</a> on top of BearSSL.
-It has no other practical purpose; you're better off directly invoking
-<a href="../s6-tlsc.html">s6-tlsc</a>.
+ The arguments are as follows:
</p>
-<h4> <code> int sbearssl_s6tlsd (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity) </code> </h4>
+<ul>
+ <li> <tt>fds</tt>&nbsp;: 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. </li>
+ <li> <tt>preoptions&nbsp;: a bitfield.
+ <ul>
+ <li> Bit 0: if clear, no client authentication is performed. If set,
+the <tt>CERTFILE</tt> and <tt>KEYFILE</tt> 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. <strong>This feature is currently
+unsupported and will not work; leave that bit clear for now.</strong> </li>
+ </ul> </li>
+ <li> <tt>options&nbsp;: a bitfield, which will be passed to
+<tt>sbearssl_run()</tt>.
+ <ul>
+ <li> Bit 0: if clear, no close_notify is performed and the engine
+will transmit EOF as received. If set, close_notify will be performed to
+end the TLS connection. </li>
+ </ul> </li>
+ <li> <em>verbosity</em> defines the engine's verbosity: the
+higher the more verbose. This parameter is currently ignored. </li>
+ <li> <tt>servername</tt>&nbsp;: the server name used for SNI. If NULL, then
+no SNI is performed, which may be a security risk. </li>
+ <li> <tt>cb</tt>&nbsp;: a pointer to a callback function, that will be
+passed as is to <tt>sbearssl_run()</tt>. </li>
+ <li> <tt>notif</tt>&nbsp;: an unsigned integer that will be embedded into
+the <em>cbarg</em> structure that will be passed to <tt>sbearssl_run()</tt>.
+It is used by <a href="../s6-tlsc-io.html">s6-tlsc-io</a> to identify a
+valid fd on which to write SSL data information once the handshake has
+completed. </li>
+</ul>
+
+<h4> <code> void sbearssl_server_init_and_run (int *fds, tain_t const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, unsigned int notif) </code> </h4>
<p>
- This function implements <a href="../s6-tlsd.html">s6-tlsd</a> on top of BearSSL.
-It has no other practical purpose; you're better off directly invoking
-<a href="../s6-tlsd.html">s6-tlsd</a>.
+ Same as the previous function, but on the server side. No <em>servername</em>
+argument is required. The <tt>CERTFILE</tt> and <tt>KEYFILE</tt> environment
+variables are mandatory, they point to the server's certificate and private
+key. It is only necessary to set <tt>CADIR</tt> or <tt>CAFILE</tt> when bit
+0 of <em>preoptions</em> is set <strong>(this functionality <em>is</em> supported server-side)</strong>,
+in which case client authentication will be
+requested, and a list of trust anchors (read from either the directory
+in <tt>CADIR</tt> or the PEM file in <tt>CAFILE</tt>) will be used to verify
+the client certificate.
</p>
</body>
diff --git a/doc/libstls/index.html b/doc/libstls/index.html
index fcd839a..f81396c 100644
--- a/doc/libstls/index.html
+++ b/doc/libstls/index.html
@@ -52,30 +52,97 @@ sysdeps directory. </li>
<h2> Programming </h2>
-<h3> Running the TLS/SSL engine </h3>
+<h3> Utilities </h3>
-<h4> <code> int stls_run (struct tls *ctx, int *fds, pid_t pid, unsigned int verbosity, uint32_t options, tain_t const *tto) </code> </h4>
+<h4> <code> void stls_drop () </code> </h4>
+
+<p>
+ 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.
+</p>
+
+<h3> Initializing the TLS engine </h3>
+
+<h4> <code> struct tls *stls_client_init_and_handshake (int const *fds, uint32_t preoptions, char const *servername) </code> </h4>
+
+<p>
+ 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 <tt>struct tls</tt> context for the
+application to pass to the <tt>stls_run</tt> 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.
+</p>
+
+<p>
+ If the <tt>CADIR</tt> 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 <tt>CAFILE</tt>
+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.
+</p>
+
+<p>
+ The arguments are as follows:
+</p>
+
+<ul>
+ <li> <tt>fds</tt>&nbsp;: 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. </li>
+ <li> <tt>preoptions&nbsp;: a bitfield.
+ <ul>
+ <li> Bit 0: if clear, no client authentication is performed. If set,
+the <tt>CERTFILE</tt> and <tt>KEYFILE</tt> 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. </li>
+ </ul> </li>
+ <li> <tt>servername</tt>&nbsp;: the server name used for SNI. If NULL, then
+no SNI is performed, which may be a security risk. </li>
+</ul>
+
+<h4> <code> struct tls *stls_server_init_and_handshake (int const *fds, uint32_t preoptions) </code> </h4>
+
+<p>
+ Same as the previous function, but on the server side. No <em>servername</em>
+argument is required. The <tt>CERTFILE</tt> and <tt>KEYFILE</tt> environment
+variables are mandatory, they point to the server's certificate and private
+key. It is only necessary to set <tt>CADIR</tt> or <tt>CAFILE</tt> when bit
+0 of <em>preoptions</em> is set, in which case client authentication will be
+requested, and a list of trust anchors (read from either the directory
+in <tt>CADIR</tt> or the PEM file in <tt>CAFILE</tt>) will be used to verify
+the client certificate.
+</p>
+
+<h3> Running the TLS engine </h3>
+
+<h4> <code> void stls_run (struct tls *ctx, int *fds, unsigned int verbosity, uint32_t options, tain_t const *tto) </code> </h4>
<p>
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) or a given subprocess dies.
+with EOF). It does not return.
</p>
<ul>
<li> <em>ctx</em> is a pointer to a fully initialized context,
connected to <em>fds</em>[2] and <em>fds</em>[3]. The TLS
handshake must already be completed. </li>
- <li> <em>fds</em> is an array of 5 file descriptors, in this
+ <li> <em>fds</em> is an array of 4 file descriptors, in this
order: fd reading clear text, fd writing clear text, fd reading
-ciphertext, fd writing ciphertext, selfpipe. </li>
- <li> <em>pid</em> is the pid of the application subprocess.
-When a SIGCHLD is detected on the selfpipe, the newly deceased
-process is reaped, and if it was <em>pid</em>, then the function
-returns as soon as it doesn't have anything left to write to
-the network peer. </li>
+ciphertext, fd writing ciphertext. </li>
<li> <em>verbosity</em> defines the engine's verbosity: the
higher the more verbose. This parameter is currently ignored. </li>
<li> <em>options</em> is a bitfield.
@@ -106,29 +173,8 @@ if you don't want the engine to ever timeout. </li>
<p>
<tt>stls_run</tt> will make the process die with an appropriate error
-message if it encounters an unrecoverable error. If there were no problems and the
-SSL/TLS connection closed cleanly, it returns -1. If the application
-subprocess dies early, <tt>stls_run</tt> returns the <em>wstat</em>
-for that subprocess, i.e. the integer containing the information about
-its exit code or crash signal. No matter how <tt>stls_run</tt> returns,
-the first four descriptors in <em>fds</em> are closed, but the
-selfpipe is untouched and the caller should free <em>ctx</em> itself.
-</p>
-
-<h4> <code> int stls_s6tlsc (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity, char const *servername, int *sfd) </code> </h4>
-
-<p>
- This function implements <a href="../s6-tlsc.html">s6-tlsc</a> on top of LibreSSL.
-It has no other practical purpose; you're better off directly invoking
-<a href="../s6-tlsc.html">s6-tlsc</a>.
-</p>
-
-<h4> <code> int stls_s6tlsd (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity) </code> </h4>
-
-<p>
- This function implements <a href="../s6-tlsd.html">s6-tlsd</a> on top of LibreSSL.
-It has no other practical purpose; you're better off directly invoking
-<a href="../s6-tlsd.html">s6-tlsd</a>.
+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.
</p>
</body>
diff --git a/doc/s6-tlsc-io.html b/doc/s6-tlsc-io.html
new file mode 100644
index 0000000..2f02841
--- /dev/null
+++ b/doc/s6-tlsc-io.html
@@ -0,0 +1,217 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-networking: the s6-tlsc-io program</title>
+ <meta name="Description" content="s6-networking: the s6-tlsc-io program" />
+ <meta name="Keywords" content="s6-networking s6-tlsc-io tlsc tls ssl ucspi tcp inet network tcp/ip client" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-networking</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-tlsc-io</tt> program </h1>
+
+<p>
+<tt>s6-tlsc-io</tt> is a program that establishes a TLS or SSL
+client connection over an existing TCP connection, then
+communicates with an existing local program over already
+established pipes. It is the only client-side program in
+s6-networking that performs cryptography.
+</p>
+
+<p>
+ <a href="index.html">s6-networking</a> does not include
+cryptographic software. All the crypto used in <tt>s6-tlsc-io</tt>
+is provided by the chosen SSL backend:
+<a href="https://bearssl.org/">BearSSL</a> or
+<a href="https://www.libressl.org/">LibreSSL</a>, depending on
+the options given when configuring s6-networking.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-tlsc-io [ -S | -s ] [ -Y | -y ] [ -v <em>verbosity</em> ] [ -K kimeout ] [ -k <em>servername</em> ] [ -d notif ] [ -- ] <em>fdr</em> <em>fdw</em>
+</pre>
+
+<ul>
+ <li> s6-tlsc-io expects to have an open connection it
+can talk to on its standard input and output. It also expects to read
+cleartext data from file descriptor <em>fdr</em> and write cleartext
+data to file descriptor <em>fdw</em>. </li>
+ <li> It initiates a TLS handshake over the network connection,
+expecting a TLS server on the other side. </li>
+ <li> Then it acts as a full duplex tunnel, decrypting and transmitting
+data from stdin to <em>fdw</em>, and encrypting and transmitting data
+from <em>fdr</em> to stdout. </li>
+ <li> When it cannot transmit any more data from/to the local application
+because connections have closed, <tt>s6-tlsc-io</tt> exits. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: the connection terminated normally.
+ <li> 96: error while configuring the TLS context - for instance, invalid trust anchor set. </li>
+ <li> 97: error while setting up the TLS client engine. </li>
+ <li> 98: TLS error while running the engine. </li>
+ <li> 100: wrong usage. </li>
+ <li> 111: system call failed. </li>
+</ul>
+
+<h2> Protocol version and parameters </h2>
+
+<p>
+ During the TLS handshake, <tt>s6-tlsc-io</tt> tries
+every version of the protocol that is supported by the
+backend, with all supported algorithms and cipher suites;
+the backend normally ensures that the most secure combination
+is tried first, with slow degradation until the client and
+the server agree.
+</p>
+
+<ul>
+ <li> For BearSSL, this means use of the
+<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#aa386dd0b03a0123760bf63df5a41c1e0">br_ssl_client_init_full()</a>
+function. The supported protocol versions are described
+<a href="https://bearssl.org/support.html#supported-versions">here</a>. </li>
+ <li> For LibreSSL, this means use of the
+<a href="https://man.openbsd.org/OpenBSD-current/man3/tls_config_set_protocols.3">tls_config_set_protocols(TLS_PROTOCOLS_ALL)</a>
+call. </li>
+</ul>
+
+<p>
+ As a client, it is better for <tt>s6-tlsc-io</tt> to adapt to as many servers
+as possible, that's why it adopts a liberal approach to protocol
+versions.
+</p>
+
+<h2> Environment variables </h2>
+
+<p>
+ <tt>s6-tlsc-io</tt> expects to have one of the
+<tt>CADIR</tt> or <tt>CAFILE</tt> environment variables set.
+It will refuse to run if both are unset. If both are set,
+<tt>CADIR</tt> has priority. The value of that variable is:
+</p>
+
+<ul>
+ <li> for <tt>CADIR</tt>: a directory where trust anchors
+(i.e. root or intermediate CA certificates) can be found,
+one per file, DER- or PEM-encoded. </li>
+ <li> for <tt>CAFILE</tt>: a file containing the whole set
+of trust anchors, PEM-encoded. </li>
+</ul>
+
+<p>
+ If you are using client certificates, s6-tlsc-io also reads
+two more environment variables: <tt>KEYFILE</tt> contains
+the path to a file containing the private key, DER- or
+PEM-encoded; and <tt>CERTFILE</tt> contains the path to
+a file containing the client certificate, DER- or
+PEM-encoded.
+</p>
+
+<p>
+ If <tt>s6-tlsc-io</tt> is run as root, it can also read two
+other environment variables, <tt>TLS_UID</tt> and <tt>TLS_GID</tt>,
+which contain a numeric uid and a numeric gid; <tt>s6-tlsc-io</tt>
+then drops its root privileges to this uid/gid after spawning
+<em>prog...</em>. This ensures that the TLS/engine and the
+application run with different privileges. Note that <em>prog...</em>
+should drop its own root privileges by its own means: the
+<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
+program is a chainloading way of doing it.
+</p>
+
+<h2> Server name determination for SNI </h2>
+
+<p>
+ The <tt>-k <em>servername</em></tt> option is important to
+<tt>s6-tlsc-io</tt>: it tells it to send <em>servername</em>
+as the name to require a certificate for.
+Not setting this option allows <tt>s6-tlsc-io</tt> to
+proceed without SNI, <strong>which may be a security risk.</strong>
+</p>
+
+<h2> SSL close handling </h2>
+
+<p>
+ If the local application initiates the end of the session by sending
+EOF to <em>fdr</em>, there are two ways for the TLS layer to handle it.
+</p>
+
+<ul>
+ <li> It can send a <tt>close_notify</tt> alert, and wait for
+an acknowledgement from the peer, at which point the connection
+is closed. The advantage of this setup is that it is secure
+even when the application protocol is not auto-terminated, i.e.
+when it does not know when its data stops. Old protocols such
+as HTTP-0.9 are in this case. The drawback of this setup is
+that it breaks full-duplex: once a peer has sent the
+<tt>close_notify</tt>, it must discard all the incoming
+records that are not a <tt>close_notify</tt> from the
+other peer. So if a client sends EOF while it is still
+receiving data from the server, the connection closes
+immediately and the data can be truncated. </li>
+ <li> It can simply transmit the EOF, shutting down
+half the TCP connection, and wait for the EOF back.
+The advantage of this setup is that it maintains
+full-duplex: a client can send EOF after its initial
+request, and still receive a complete answer from the
+server. The drawback is that it is insecure when the application
+protocol is not auto-terminated. </li>
+</ul>
+
+<p>
+ Nowadays (2020), most protocols are auto-terminated, so
+it is not dangerous anymore to use EOF tranmission, and that
+is the default for <tt>s6-tlsc-io</tt>. Nevertheless, by
+using the <tt>-S</tt> option, you can
+force it to use the <tt>close_notify</tt> method if your
+application requires it to be secure.
+</p>
+
+<h2> <tt>s6-tlsc-io</tt> options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
+verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
+verbose, more than 2 is debug output. This option currently has
+no effect. </li>
+ <li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
+and break the connection when receiving a local EOF. </li>
+ <li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
+connection without using <tt>close_notify</tt>. This is the default. </li>
+ <li> <tt>-Y</tt>&nbsp;: Do not send a client certificate. This is the default. </li>
+ <li> <tt>-y</tt>&nbsp;: Send a client certificate. </li>
+ <li> <tt>-k&nbsp;<em>servername</em></tt>&nbsp;: use Server Name
+Indication, and send <em>servername</em>. The default is not to
+use SNI, which may be a security risk. </li>
+ <li> <tt>-K&nbsp;<em>kimeout</em></tt>&nbsp;: close the connection
+if <em>kimeout</em> milliseconds elapse without any data being
+received from either side. The default is 0, which means
+infinite timeout (never kill the connection). </li>
+ <li> <tt>-d&nbsp;<em>notif</em></tt>&nbsp;: handshake notification.
+<em>notif</em> must be a file descriptor open for writing. When the
+TLS handshake has completed, some data (terminated by two null
+characters) will be sent to file descriptor <em>notif</em>. The
+data contains information about the TLS parameters of the connection;
+its exact contents are left unspecified, but there's at least
+a <tt>SSL_PROTOCOL=<em>protocol</em></tt> string
+and a <tt>SSL_CIPHER=<em>cipher</em></tt> string, both null-terminated.
+Sending this data serves a dual purpose: telling the <em>notif</em>
+reader that the handshake has completed, and providing it with some
+basic information about the connection. If this option is not given,
+no such notification is performed. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-tlsc.html b/doc/s6-tlsc.html
index 1237460..c2e7521 100644
--- a/doc/s6-tlsc.html
+++ b/doc/s6-tlsc.html
@@ -20,21 +20,12 @@
<p>
<tt>s6-tlsc</tt> is a program that establishes a TLS or SSL
-client connection over an existing TCP connection, then spawns
-an application. It is meant to make network communications
+client connection over an existing TCP connection, then execs
+into an application. It is meant to make network communications
secure even for applications that do not natively support
TLS/SSL.
</p>
-<p>
- <a href="index.html">s6-networking</a> does not include
-cryptographic software. All the crypto used in <tt>s6-tlsc</tt>
-is provided by the chosen SSL backend:
-<a href="https://bearssl.org/">BearSSL</a> or
-<a href="https://www.libressl.org/">LibreSSL</a>, depending on
-the options given when configuring <tt>s6-networking</tt>.
-</p>
-
<h2> Interface </h2>
<pre>
@@ -45,60 +36,25 @@ the options given when configuring <tt>s6-networking</tt>.
<li> s6-tlsc expects to have an open TCP connection it
can talk to on its (by default) descriptors 6 (for reading)
and 7 (for writing). </li>
- <li> It spawns <em>prog...</em> as a child process,
-interposing itself between it and the network. </li>
- <li> It initiates a TLS/SSL handshake over the
-network connection, expecting a TLS/SSL server on the other
-side. </li>
- <li> It manages the encryption/decryption of all the
-messages between <em>prog</em> and the server.
-<em>prog</em> speaks plaintext, but only ciphertext is sent
-on the network. </li>
- <li> When <em>prog</em> exits, <tt>s6-tlsc</tt> exits.
+ <li> It spawns a <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+child process that will initiate the TLS connection, perform the
+handshake (expecting a TLS server on the other side of the
+network) and maintain the TLS tunnel. </li>
+ <li> When notified by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+that the handshake has completed, s6-tlsc execs into
+<em>prog...</em>. </li>
</ul>
<h2> Exit codes </h2>
<ul>
- <li> 96: error while configuring the TLS/SSL context - for instance, invalid trust anchor set. </li>
- <li> 97: error while setting up the TLS/SSL client engine. </li>
- <li> 98: TLS/SSL error while running the engine. </li>
<li> 100: wrong usage. </li>
<li> 111: system call failed. </li>
</ul>
<p>
- If the TLS/SSL connection closes cleanly, <tt>s6-tlsc</tt>
-waits for <em>prog</em> to exit, then exits with an
-<a href="//skarnet.org/software/execline/exitcodes.html">approximation</a>
-of <em>prog</em>'s exit code.
-</p>
-
-<h2> Protocol version and parameters </h2>
-
-<p>
- During the TLS/SSL handshake, <tt>s6-tlsc</tt> tries
-every version of the protocol that is supported by the
-backend, with all supported algorithms and cipher suites;
-the backend normally ensures that the most secure combination
-is tried first, with slow degradation until the client and
-the server agree.
-</p>
-
-<ul>
- <li> For BearSSL, this means use of the
-<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#aa386dd0b03a0123760bf63df5a41c1e0">br_ssl_client_init_full()</a>
-function. The supported protocol versions are described
-<a href="https://bearssl.org/support.html#supported-versions">here</a>. </li>
- <li> For LibreSSL, this means use of the
-<a href="https://man.openbsd.org/OpenBSD-current/man3/tls_config_set_protocols.3">tls_config_set_protocols(TLS_PROTOCOLS_ALL)</a>
-call. </li>
-</ul>
-
-<p>
- As a client, it is better for <tt>s6-tlsc</tt> to adapt to as many servers
-as possible, that's why it adopts a liberal approach to protocol
-versions.
+ If everything goes smoothly, s6-tlsc does not exit, but execs
+into <em>prog...</em> instead.
</p>
<h2> Environment variables </h2>
@@ -106,110 +62,44 @@ versions.
<h3> Read </h3>
<p>
- <tt>s6-tlsc</tt> expects to have one of the
-<tt>CADIR</tt> or <tt>CAFILE</tt> environment variables set.
-It will refuse to run if both are unset. If both are set,
-<tt>CADIR</tt> has priority. The value of that variable is:
+ s6-tlsc does not expect to have any particular
+environment variables, but it spawns a
+<a href="s6-tlsc-io.html">s6-tlsc-io</a> program that does.
+So it should pay attention to the following variables:
</p>
<ul>
- <li> for <tt>CADIR</tt>: a directory where trust anchors
-(i.e. root or intermediate CA certificates) can be found,
-one per file, DER- or PEM-encoded. </li>
- <li> for <tt>CAFILE</tt>: a file containing the whole set
-of trust anchors, PEM-encoded. </li>
+ <li> <tt>CADIR</tt> or <tt>CAFILE</tt> </li>
+ <li> (if the -y option has been given) <tt>CERTFILE</tt> and <tt>KEYFILE</tt> </li>
+ <li> <tt>TLS_UID</tt> and <tt>TLS_GID</tt>
</ul>
-<p>
- If you are using client certificates, s6-tlsc also reads
-two more environment variables: <tt>KEYFILE</tt> contains
-the path to a file containing the private key, DER- or
-PEM-encoded; and <tt>CERTFILE</tt> contains the path to
-a file containing the client certificate, DER- or
-PEM-encoded.
-</p>
-
-<p>
- If <tt>s6-tlsc</tt> is run as root, it can also read two
-other environment variables, <tt>TLS_UID</tt> and <tt>TLS_GID</tt>,
-which contain a numeric uid and a numeric gid; <tt>s6-tlsc</tt>
-then drops its root privileges to this uid/gid after spawning
-<em>prog...</em>. This ensures that the TLS/engine and the
-application run with different privileges. Note that <em>prog...</em>
-should drop its own root privileges by its own means: the
-<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
-program is a way of doing it.
-</p>
-
<h3> Written </h3>
<p>
- Unless the <tt>-Z</tt> option has been given to
-<tt>s6-tlsc</tt>, <em>prog...</em> is run with all the
-TLS/SSL variables <em>unset</em>: CADIR, CAFILE,
-KEYFILE, CERTFILE, TLS_UID and TLS_GID. The goal is
-for <tt>s6-tlsc</tt> to be, by default, as invisible
-as possible.
-</p>
-
-<h2> Server name determination for SNI </h2>
-
-<p>
- The <tt>-k <em>servername</em></tt> option is important to
-<tt>s6-tlsc</tt>: it tells it to send <em>servername</em>
-as the name to require a certificate for.
-Not setting this option allows <tt>s6-tlsc</tt> to
-proceed without SNI,
-<strong>which may be a security risk.</strong>
+ By default, <em>prog...</em> is run with all these
+variables <em>unset</em>: CADIR, CAFILE,
+KEYFILE, CERTFILE, TLS_UID and TLS_GID. They're passed to
+the <a href="s6-tlsc-io.html">s6-tlsc-io</a> child but
+not to <em>prog...</em>.
+The <tt>-Z</tt> option prevents that behaviour.
</p>
<p>
- The <a href="s6-tlsclient.html">s6-tlsclient</a> program can
-automatically craft a <tt>-k</tt> option for <tt>s6-tlsc</tt>
-if the <em>host</em> argument that is given to it is a
-host name. But if you're invoking <tt>s6-tlsc</tt> directly,
-do not forget to give it this option.
-</p>
-
-<h2> SSL close handling </h2>
-
-<p>
- If <em>prog</em> initiates the end of the session by sending
-EOF, there are two ways for the TLS/SSL layer to handle it.
+ However, <em>prog...</em> is run with the following additional
+environment variables:
</p>
<ul>
- <li> It can send a <tt>close_notify</tt> alert, and wait for
-an acknowledgement from the peer, at which point the connection
-is closed. The advantage of this setup is that it is secure
-even when the application protocol is not auto-terminated, i.e.
-when it does not know when its data stops. Old protocols such
-as HTTP-0.9 are in this case. The drawback of this setup is
-that it breaks full-duplex: once a peer has sent the
-<tt>close_notify</tt>, it must discard all the incoming
-records that are not a <tt>close_notify</tt> from the
-other peer. So if a client sends EOF while it is still
-receiving data from the server, the connection closes
-immediately and the data can be truncated. </li>
- <li> It can simply transmit the EOF, shutting down
-half the TCP connection, and wait for the EOF back.
-The advantage of this setup is that it maintains
-full-duplex: a client can send EOF after its initial
-request, and still receive a complete answer from the
-server. The drawback is that it is insecure when the application
-protocol is not auto-terminated. </li>
+ <li> <tt>SSL_PROTOCOL</tt> contains the protocol version:
+TLSv1, TLSv1.1, TLSv1.2... </li>
+ <li> <tt>SSL_CIPHER</tt> contains the name of the cipher
+used. </li>
+ <li> More similar environment variables containing information
+about the connection may be added in the future. </li>
</ul>
-<p>
- Nowadays (2017), most protocols are auto-terminated, so
-it is not dangerous anymore to use EOF tranmission, and that
-is the default for <tt>s6-tlsc</tt>. Nevertheless, by
-using the <tt>-S</tt> option, you can
-force it to use the <tt>close_notify</tt> method if your
-application requires it to be secure.
-</p>
-
-<h2> <tt>s6-tlsc</tt> options </h2>
+<h2> Options </h2>
<ul>
<li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
@@ -217,10 +107,11 @@ verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
verbose, more than 2 is debug output. This option currently has
no effect. </li>
<li> <tt>-Z</tt>&nbsp;: do not clean the environment of
-<tt>s6-tlsc</tt>-related variables before spawning <em>prog...</em>. </li>
+the variables used by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+before execing <em>prog...</em>. </li>
<li> <tt>-z</tt>&nbsp;: clean the environment of
-<tt>s6-tlsc</tt>-related variables before spawning <em>prog...</em>.
-This is the default. </li>
+the variables used by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+before execing <em>prog...</em>. This is the default. </li>
<li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
and break the connection when <em>prog</em> sends EOF. </li>
<li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
@@ -234,20 +125,20 @@ use SNI, which may be a security risk. </li>
if <em>kimeout</em> milliseconds elapse without any data being
received from either side. The default is 0, which means
infinite timeout (never kill the connection). </li>
- <li> <tt>-6&nbsp;<em>rfd</em></tt>&nbsp;: expect an open file
-descriptor numbered <em>rfd</em> to read network (ciphertext)
+ <li> <tt>-6&nbsp;<em>fdr</em></tt>&nbsp;: expect an open file
+descriptor numbered <em>fdr</em> to read network (ciphertext)
data from. Make sure <em>prog</em> also reads its data
-from its own fd <em>rfd</em>. Default is 6. </li>
- <li> <tt>-7&nbsp;<em>wfd</em></tt>&nbsp;: expect an open file
-descriptor numbered <em>wfd</em> to write network (ciphertext)
+from its own fd <em>fdr</em>. Default is 6. </li>
+ <li> <tt>-7&nbsp;<em>fdw</em></tt>&nbsp;: expect an open file
+descriptor numbered <em>fdw</em> to write network (ciphertext)
data to. Make sure <em>prog</em> also writes its data to
-its own fd <em>wfd</em>. Default is 7. </li>
+its own fd <em>fdw</em>. Default is 7. </li>
</ul>
<h2> Notes </h2>
<ul>
- <li> The goal of the <tt>s6-tlsc</tt> interface (and its
+ <li> The goal of the s6-tlsc interface (and its
server-side companion <a href="s6-tlsd.html">s6-tlsd</a>) is to
make it so that if you have a client, run by the command line
<tt>client...</tt> that speaks a cleartext protocol to a server
diff --git a/doc/s6-tlsclient.html b/doc/s6-tlsclient.html
index 2553637..fc357a7 100644
--- a/doc/s6-tlsclient.html
+++ b/doc/s6-tlsclient.html
@@ -40,22 +40,20 @@ involving:
establishes a TCP connection to host <em>host</em> port <em>port</em>. </li>
<li> <a href="s6-tlsc.html">s6-tlsc</a>, which establishes
a TLS transport (client-side) over that connection. </li>
- <li> <em>prog...</em>, your client program, which is run as a
-child of <a href="s6-tlsc.html">s6-tlsc</a>. </li>
+ <li> <em>prog...</em>, your client program, which is executed into by
+<a href="s6-tlsc.html">s6-tlsc</a> once the
+<a href="s6-tlsc-io.html">s6-tlsc-io</a> child it has spawned has
+set up the TLS connection and performed the handshake. </li>
</ul> </li>
- <li> It runs until the connection closes. </li>
- <li> It exits either with a <a href="s6-tlsc.html">s6-tlsc</a>
-error code (and error message), or with an
-<a href="https://skarnet.org/software/execline/exitcodes.html">approximation</a>
-of <em>prog</em>'s exit code. </li>
+ <li> <em>prog...</em> is run with the same pid as s6-tlsclient. </li>
</ul>
<p>
<em>prog</em> is expected to read from its peer on
descriptor 6 and write to its peer on descriptor 7.
-Since there will be a <a href="s6-tlsc.html">s6-tlsc</a>
+Since there will be a <a href="s6-tlsc-io.html">s6-tlsc-io</a>
program between <em>prog</em> and the network to perform
-the SSL encryption/decryption, those descriptors will not
+the TLS encryption/decryption, those descriptors will not
be a network socket - they will be pipes.
</p>
@@ -79,7 +77,7 @@ used, which may be a security risk.</strong>
<p>
The following variables should be set before invoking
<tt>s6-tlsclient</tt>, because they will be used by
-<a href="s6-tlsc.html">s6-tlsc</a>:
+<a href="s6-tlsc-io.html">s6-tlsc-io</a>:
</p>
<ul>
diff --git a/doc/s6-tlsd-io.html b/doc/s6-tlsd-io.html
new file mode 100644
index 0000000..6aad7dc
--- /dev/null
+++ b/doc/s6-tlsd-io.html
@@ -0,0 +1,212 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-networking: the s6-tlsc-io program</title>
+ <meta name="Description" content="s6-networking: the s6-tlsc-io program" />
+ <meta name="Keywords" content="s6-networking s6-tlsc-io tlsc tls ssl ucspi tcp inet network tcp/ip client" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-networking</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-tlsc-io</tt> program </h1>
+
+<p>
+<tt>s6-tlsd-io</tt> is a program that establishes a TLS or SSL
+server connection over an existing TCP connection, then
+communicates with an existing local program over already
+established pipes. It is the only server-side program in
+s6-networking that performs cryptography.
+</p>
+
+<p>
+ <a href="index.html">s6-networking</a> does not include
+cryptographic software. All the crypto used in <tt>s6-tlsd-io</tt>
+is provided by the chosen SSL backend:
+<a href="https://bearssl.org/">BearSSL</a> or
+<a href="https://www.libressl.org/">LibreSSL</a>, depending on
+the options given when configuring s6-networking.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-tlsd-io [ -S | -s ] [ -Y | -y ] [ -v <em>verbosity</em> ] [ -K kimeout ] [ -d notif ] [ -- ] <em>fdr</em> <em>fdw</em>
+</pre>
+
+<ul>
+ <li> s6-tlsd-io expects to have an open connection it
+can talk to on its standard input and output. It also expects to read
+cleartext data from file descriptor <em>fdr</em> and write cleartext
+data to file descriptor <em>fdw</em>. </li>
+ <li> It expects a TLS client on the other side of the network connection
+to initiate a TLS handshake, and it answers it. </li>
+ <li> Then it acts as a full duplex tunnel, decrypting and transmitting
+data from stdin to <em>fdw</em>, and encrypting and transmitting data
+from <em>fdr</em> to stdout. </li>
+ <li> When it cannot transmit any more data from/to the local application
+because connections have closed, <tt>s6-tlsd-io</tt> exits. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: the connection terminated normally.
+ <li> 96: error while configuring the TLS context - for instance, invalid private key or server certificate files. </li>
+ <li> 97: error while setting up the TLS server engine. </li>
+ <li> 98: TLS error while running the engine. </li>
+ <li> 100: wrong usage. </li>
+ <li> 111: system call failed. </li>
+</ul>
+
+<h2> Protocol version and parameters </h2>
+
+<p>
+ During the TLS/SSL handshake, <tt>s6-tlsd-io</tt> tries the
+versions of the protocol that is supported by default by the
+backend, with the default algorithms and cipher suites;
+the backend normally ensures that the most secure combination
+is tried first, with slow degradation until the client and
+the server agree.
+</p>
+
+<ul>
+ <li> For BearSSL, this means use of the
+<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a76293c81c4624c58254a62be7b2d5e79">br_ssl_server_init_full_rsa()</a> or
+<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a592b2af27b2f6b9389aac854fb0b783a">br_ssl_server_init_full_ec()</a>
+function. The supported protocol versions are described
+<a href="https://bearssl.org/support.html#supported-versions">here</a>. </li>
+ <li> For LibreSSL, this means use of the
+<a href="https://man.openbsd.org/OpenBSD-current/man3/tls_config_set_protocols.3">tls_config_set_protocols(TLS_PROTOCOLS_DEFAULT)</a>
+call. </li>
+</ul>
+
+<p>
+ As a server, <tt>s6-tlsd-io</tt> can be conservative in its
+choice of protocols. It is currently not very conservative
+when using the BearSSL backend; it could become more so in
+the future, by defining a custom server profile that supports
+only TLS-1.2 but with several algorithms and cipher suites.
+</p>
+
+<h2> Environment variables </h2>
+
+<p>
+ <tt>s6-tlsd-io</tt> expects to have the following
+environment variables set:
+</p>
+
+<ul>
+ <li> <tt>KEYFILE</tt>: a path to the file
+containing the server's private key, DER- or PEM-encoded. </li>
+ <li> <tt>CERTFILE</tt>: a path to the file
+containing the server's certificate, DER- or PEM-encoded.
+If PEM-encoded, the file can actually contain a chain
+of certificates. </li>
+</ul>
+
+<p>
+ If one of those variables is unset, <tt>s6-tlsd-io</tt>
+will refuse to run.
+</p>
+
+<p>
+ If you are using client certificats, <tt>s6-tlsd-io</tt>
+also requires either one of the following variables to be set:
+</p>
+
+<ul>
+ <li> <tt>CADIR</tt>: a directory where trust anchors
+(i.e. root or intermediate CA certificates) can be found,
+one per file, DER- or PEM-encoded. </li>
+ <li> <tt>CAFILE</tt>: a file containing the whole set
+of trust anchors, PEM-encoded. </li>
+</ul>
+
+<p>
+ If <tt>s6-tlsd-io</tt> is run as root, it can also read two
+more environment variables, <tt>TLS_UID</tt> and <tt>TLS_GID</tt>,
+which contain a numeric uid and a numeric gid; <tt>s6-tlsd-io</tt>
+then drops its root privileges to this uid/gid after reading its
+private key file. This ensures that the engine, including the
+handshake, is run with as little privilege as possible.
+</p>
+
+<h2> SSL close handling </h2>
+
+<p>
+ If the local application initiates the end of the session by sending
+EOF to <em>fdr</em>, there are two ways for the TLS layer to handle it.
+</p>
+
+<ul>
+ <li> It can send a <tt>close_notify</tt> alert, and wait for
+an acknowledgement from the peer, at which point the connection
+is closed. The advantage of this setup is that it is secure
+even when the application protocol is not auto-terminated, i.e.
+when it does not know when its data stops. Old protocols such
+as HTTP-0.9 are in this case. The drawback of this setup is
+that it breaks full-duplex: once a peer has sent the
+<tt>close_notify</tt>, it must discard all the incoming
+records that are not a <tt>close_notify</tt> from the
+other peer. So if a client sends EOF while it is still
+receiving data from the server, the connection closes
+immediately and the data can be truncated. </li>
+ <li> It can simply transmit the EOF, shutting down
+half the TCP connection, and wait for the EOF back.
+The advantage of this setup is that it maintains
+full-duplex: a client can send EOF after its initial
+request, and still receive a complete answer from the
+server. The drawback is that it is insecure when the application
+protocol is not auto-terminated. </li>
+</ul>
+
+<p>
+ Nowadays (2020), most protocols are auto-terminated, so
+it is not dangerous anymore to use EOF tranmission, and that
+is the default for <tt>s6-tlsd-io</tt>. Nevertheless, by
+using the <tt>-S</tt> option, you can
+force it to use the <tt>close_notify</tt> method if your
+application requires it to be secure.
+</p>
+
+<h2> <tt>s6-tlsd-io</tt> options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
+verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
+verbose, more than 2 is debug output. This option currently has
+no effect. </li>
+ <li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
+and break the connection when receiving a local EOF. </li>
+ <li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
+connection without using <tt>close_notify</tt>. This is the default. </li>
+ <li> <tt>-Y</tt>&nbsp;: Do not send a client certificate. This is the default. </li>
+ <li> <tt>-y</tt>&nbsp;: Send a client certificate. </li>
+ <li> <tt>-K&nbsp;<em>kimeout</em></tt>&nbsp;: close the connection
+if <em>kimeout</em> milliseconds elapse without any data being
+received from either side. The default is 0, which means
+infinite timeout (never kill the connection). </li>
+ <li> <tt>-d&nbsp;<em>notif</em></tt>&nbsp;: handshake notification.
+<em>notif</em> must be a file descriptor open for writing. When the
+TLS handshake has completed, some data (terminated by two null
+characters) will be sent to file descriptor <em>notif</em>. The
+data contains information about the TLS parameters of the connection;
+its exact contents are left unspecified, but there's at least
+a <tt>SSL_PROTOCOL=<em>protocol</em></tt> string
+and a <tt>SSL_CIPHER=<em>cipher</em></tt> string, both null-terminated.
+Sending this data serves a dual purpose: telling the <em>notif</em>
+reader that the handshake has completed, and providing it with some
+basic information about the connection. If this option is not given,
+no such notification is performed. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-tlsd.html b/doc/s6-tlsd.html
index 36125d2..beeedda 100644
--- a/doc/s6-tlsd.html
+++ b/doc/s6-tlsd.html
@@ -20,8 +20,8 @@
<p>
<tt>s6-tlsd</tt> is a program that performs the server side of
-a TLS or SSL connection over an existing TCP connection, then spawns
-an application. It is meant to make network communications
+a TLS or SSL connection over an existing TCP connection, then execs
+into an application. It is meant to make network communications
secure even for applications that do not natively support
TLS/SSL.
</p>
@@ -45,69 +45,25 @@ the options given when configuring <tt>s6-networking</tt>.
<li> s6-tlsd expects to have an open TCP connection it
can talk to on its stdin (for reading) and stdout
(for writing). </li>
- <li> It spawns <em>prog...</em> as a child process,
-interposing itself between it and the network.
-In other words: <em>prog</em> still reads cleartext
-on its stdin and writes cleartext on its stdout, but
-those will actually be pipes to <tt>s6-tlsd</tt>, which
-will read ciphertext from its own stdin (the network)
-and write ciphertext to its own stdout (the network). </li>
- <li> It initiates the server side of a TLS/SSL handshake
-over the network connection, expecting a TLS/SSL client on
-the other side. </li>
- <li> It manages the encryption/decryption of all the
-messages between <em>prog</em> and the client.
-<em>prog</em> speaks plaintext, but only ciphertext is sent
-on the network. </li>
- <li> When <em>prog</em> exits, <tt>s6-tlsd</tt> exits.
+ <li> It spawns a <a href="s6-tlsd-io.html">s6-tlsd-io</a>
+child process that will be the server-side of a TLS connection,
+perform the handshake (expecting a TLS client on the other side
+of the network) and maintain the TLS tunnel. </li>
+ <li> When notified by <a href="s6-tlsd-io.html">s6-tlsd-io</a>
+that the handshake has completed, s6-tlsd execs into
+<em>prog...</em>. </li>
</ul>
<h2> Exit codes </h2>
<ul>
- <li> 96: error while configuring the TLS/SSL context - for instance, invalid
-private key or server certificate files. </li>
- <li> 97: error while setting up the TLS/SSL client engine. </li>
- <li> 98: TLS/SSL error while running the engine. </li>
<li> 100: wrong usage. </li>
<li> 111: system call failed. </li>
</ul>
<p>
- If the TLS/SSL connection closes cleanly, <tt>s6-tlsd</tt>
-waits for <em>prog</em> to exit, then exits with an
-<a href="//skarnet.org/software/execline/exitcodes.html">approximation</a>
-of <em>prog</em>'s exit code.
-</p>
-
-<h2> Protocol version and parameters </h2>
-
-<p>
- During the TLS/SSL handshake, <tt>s6-tlsd</tt> tries the
-versions of the protocol that is supported by default by the
-backend, with the default algorithms and cipher suites;
-the backend normally ensures that the most secure combination
-is tried first, with slow degradation until the client and
-the server agree.
-</p>
-
-<ul>
- <li> For BearSSL, this means use of the
-<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a76293c81c4624c58254a62be7b2d5e79">br_ssl_server_init_full_rsa()</a> or
-<a href="https://bearssl.org/apidoc/bearssl__ssl_8h.html#a592b2af27b2f6b9389aac854fb0b783a">br_ssl_server_init_full_ec()</a>
-function. The supported protocol versions are described
-<a href="https://bearssl.org/support.html#supported-versions">here</a>. </li>
- <li> For LibreSSL, this means use of the
-<a href="https://man.openbsd.org/OpenBSD-current/man3/tls_config_set_protocols.3">tls_config_set_protocols(TLS_PROTOCOLS_DEFAULT)</a>
-call. </li>
-</ul>
-
-<p>
- As a server, <tt>s6-tlsd</tt> can be conservative in its
-choice of protocols. It is currently not very conservative
-when using the BearSSL backend; it could become more so in
-the future, by defining a custom server profile that supports
-only TLS-1.2 but with several algorithms and cipher suites.
+ If everything goes smoothly, s6-tlsd does not exit, but execs
+into <em>prog...</em> instead.
</p>
<h2> Environment variables </h2>
@@ -115,120 +71,44 @@ only TLS-1.2 but with several algorithms and cipher suites.
<h3> Read </h3>
<p>
- <tt>s6-tlsd</tt> expects to have the following
-environment variables set:
-</p>
-
-<ul>
- <li> <tt>KEYFILE</tt>: a path to the file
-containing the server's private key, DER- or PEM-encoded. </li>
- <li> <tt>CERTFILE</tt>: a path to the file
-containing the server's certificate, DER- or PEM-encoded.
-If PEM-encoded, the file can actually contain a chain
-of certificates. </li>
-</ul>
-
-<p>
- If one of those variables is unset, <tt>s6-tlsd</tt>
-will refuse to run.
-</p>
-
-<p>
- If you are using client certificats, <tt>s6-tlsd</tt>
-also requires either one of the following variables to be set:
-</p>
-
-<ul>
- <li> <tt>CADIR</tt>: a directory where trust anchors
-(i.e. root or intermediate CA certificates) can be found,
-one per file, DER- or PEM-encoded. </li>
- <li> <tt>CAFILE</tt>: a file containing the whole set
-of trust anchors, PEM-encoded. </li>
-</ul>
-
-<p>
- If <tt>s6-tlsd</tt> is run as root, it can also read two
-more environment variables, <tt>TLS_UID</tt> and <tt>TLS_GID</tt>,
-which contain a numeric uid and a numeric gid; <tt>s6-tlsd</tt>
-then drops its root privileges to this uid/gid after spawning
-<em>prog...</em>. This ensures that the TLS/engine and the
-application run with different privileges.
-</p>
-
-<p>
- Note that <em>prog...</em>
-should drop its own root privileges by its own means: the
-<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
-program is a way of doing it. If the <tt>s6-tlsd</tt>
-invocation actually comes from a
-<a href="s6-tlsserver.html">s6-tlsserver</a> command line,
-and privilege-dropping options (<tt>-G</tt>, <tt>-g</tt>,
-<tt>-u</tt> or <tt>-U</tt>) have been given to
-<a href="s6-tlsserver.html">s6-tlsserver</a>, then
-<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>
-directly follows <tt>s6-tlsd</tt> on the command line, in order
-to also drop the child's privileges before executing the application.
-The point of that setup is:
+ s6-tlsd does not expect to have any particular
+environment variables, but it spawns a
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> program that does.
+So it should pay attention to the following variables:
</p>
<ul>
- <li> To read the private key file as root </li>
- <li> To run the application as a non-root user </li>
- <li> To run <tt>s6-tlsd</tt> as a <em>different</em> non-root user </li>
- <li> That way, even if <tt>s6-tlsd</tt>, the application, or both,
-get compromised, the private key is still secure. </li>
+ <li> <tt>KEYFILE</tt> and <tt>CERTFILE</tt> </li>
+ <li> (if the -y or -Y option has been given) <tt>CADIR</tt> or <tt>CAFILE</tt> </li>
+ <li> <tt>TLS_UID</tt> and <tt>TLS_GID</tt>
</ul>
<h3> Written </h3>
<p>
- Unless the <tt>-Z</tt> option has been given to
-<tt>s6-tlsd</tt>, <em>prog...</em> is run with all the
-TLS/SSL variables <em>unset</em>: CADIR, CAFILE,
-KEYFILE, CERTFILE, TLS_UID and TLS_GID. The goal is
-for <tt>s6-tlsd</tt> to be, by default, as invisible
-as possible.
+ By default, <em>prog...</em> is run with all these
+variables <em>unset</em>: CADIR, CAFILE,
+KEYFILE, CERTFILE, TLS_UID and TLS_GID. They're passed to
+the <a href="s6-tlsd-io.html">s6-tlsd-io</a> child but
+not to <em>prog...</em>.
+The <tt>-Z</tt> option prevents that behaviour.
</p>
-<h2> SSL close handling </h2>
-
<p>
- If <em>prog</em> initiates the end of the session by sending
-EOF, there are two ways for the TLS/SSL layer to handle it.
+ However, <em>prog...</em> is run with the following additional
+environment variables:
</p>
<ul>
- <li> It can send a <tt>close_notify</tt> alert, and wait for
-an acknowledgement from the peer, at which point the connection
-is closed. The advantage of this setup is that it is secure
-even when the application protocol is not auto-terminated, i.e.
-when it does not know when its data stops. Old protocols such
-as HTTP-0.9 are in this case. The drawback of this setup is
-that it breaks full-duplex: once a peer has sent the
-<tt>close_notify</tt>, it must discard all the incoming
-records that are not a <tt>close_notify</tt> from the
-other peer. So if a client sends EOF while it is still
-receiving data from the server, the connection closes
-immediately and the data can be truncated. </li>
- <li> It can simply transmit the EOF, shutting down
-half the TCP connection, and wait for the EOF back.
-The advantage of this setup is that it maintains
-full-duplex: a client can send EOF after its initial
-request, and still receive a complete answer from the
-server. The drawback is that it is insecure when the application
-protocol is not auto-terminated. </li>
+ <li> <tt>SSL_PROTOCOL</tt> contains the protocol version:
+TLSv1, TLSv1.1, TLSv1.2... </li>
+ <li> <tt>SSL_CIPHER</tt> contains the name of the cipher
+used. </li>
+ <li> More similar environment variables containing information
+about the connection may be added in the future. </li>
</ul>
-<p>
- Nowadays (2017), most protocols are auto-terminated, so
-it is not dangerous anymore to use EOF tranmission, and that
-is the default for <tt>s6-tlsd</tt>. Nevertheless, by
-using the <tt>-S</tt> option, you can
-force it to use the <tt>close_notify</tt> method if your
-application requires it to be secure.
-</p>
-
-<h2> <tt>s6-tlsd</tt> options </h2>
+<h2> Options </h2>
<ul>
<li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
@@ -236,10 +116,11 @@ verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
verbose, more than 2 is debug output. This option currently has
no effect. </li>
<li> <tt>-Z</tt>&nbsp;: do not clean the environment of
-<tt>s6-tlsd</tt>-related variables before spawning <em>prog...</em>. </li>
+the variables used by <a href="s6-tlsd-io.html">s6-tlsd-io</a>
+before execing <em>prog...</em>. </li>
<li> <tt>-z</tt>&nbsp;: clean the environment of
-<tt>s6-tlsd</tt>-related variables before spawning <em>prog...</em>.
-This is the default. </li>
+the variables used by <a href="s6-tlsd-io.html">s6-tlsd-io</a>
+before execing <em>prog...</em>. This is the default. </li>
<li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
and break the connection when <em>prog</em> sends EOF. </li>
<li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
diff --git a/doc/s6-tlsserver.html b/doc/s6-tlsserver.html
index a87fbb7..04d9951 100644
--- a/doc/s6-tlsserver.html
+++ b/doc/s6-tlsserver.html
@@ -21,7 +21,7 @@
<p>
<tt>s6-tlsserver</tt> is an
<a href="https://cr.yp.to/proto/ucspi.txt">UCSPI server tool</a> for
-TLS/SSL connections over INET domain sockets. It acts as a TCP superserver
+TLS/SSL connections over INET domain sockets. It acts as a TCP super-server
that listens to connections, accepts them, and for each connection,
establishes a TLS transport over it, then executes into a program.
</p>
@@ -49,12 +49,13 @@ than what you originally wrote. This is normal and healthy. </li>
which performs TCP access control and various operations on the
TCP connection. </li>
<li> <a href="s6-tlsd.html">s6-tlsd</a>, which establishes
-a TLS transport (server-side) over a connection. </li>
+a TLS transport (server-side) over a connection, via a
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> child process. </li>
<li> (if applicable)
<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>,
which drops root privileges. </li>
- <li> <em>prog...</em>, your client program, which is run as a
-child of <a href="s6-tlsd.html">s6-tlsd</a>. </li>
+ <li> <em>prog...</em>, your client program, which is run with the
+same pid as <a href="s6-tlsd.html">s6-tlsd</a>. </li>
</ul> </li>
<li> It runs until it is killed by a signal. </li>
</ul>
@@ -62,7 +63,7 @@ child of <a href="s6-tlsd.html">s6-tlsd</a>. </li>
<p>
<em>prog</em> is expected to read from its peer on its
standard input and write to its peer on its standard output.
-Since there will be a <a href="s6-tlsd.html">s6-tlsd</a>
+Since there will be a <a href="s6-tlsd-io.html">s6-tlsd-io</a>
program between <em>prog</em> and the network to perform
the SSL encryption/decryption, those descriptors will not
be a network socket - they will be pipes.
diff --git a/doc/s6-ucspitlsc.html b/doc/s6-ucspitlsc.html
new file mode 100644
index 0000000..4c1d2be
--- /dev/null
+++ b/doc/s6-ucspitlsc.html
@@ -0,0 +1,178 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-networking: the s6-ucspitlsc program</title>
+ <meta name="Description" content="s6-networking: the s6-ucspitlsc program" />
+ <meta name="Keywords" content="s6-networking s6-ucspitlsc tlsc tls ssl ucspi ucspi-tls delayed encryption opportunistic tls tcp inet network tcp/ip client" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-networking</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-ucspitlsc</tt> program </h1>
+
+<p>
+<tt>s6-ucspitlsc</tt> is a client-side program that establishes
+communication channels according to the UCSPI-TLS protocol,
+then execs into an application. Later, if the application sends
+a command, a TLS tunnel will be started and the application will
+be able to use it instead of communicating with the network via
+cleartext.
+</p>
+
+<p>
+ The point of this protocol, and this program, is to make it easy
+to implement commands like SMTP's STARTTLS without embedding a
+TLS stack in the client itself.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-ucspitlsc [ -S | -s ] [ -Y | -y ] [ -Z | -z ] [ -v <em>verbosity</em> ] [ -K kimeout ] [ -k <em>servername</em> ] [ -6 <em>rfd</em> ] [ -7 <em>wfd</em> ] [ -- ] <em>prog...</em>
+</pre>
+
+<ul>
+ <li> s6-ucspitlsc expects to have an open TCP connection it
+can talk to on its (by default) descriptors 6 (for reading)
+and 7 (for writing). </li>
+ <li> It forks and establishes communication channels between
+the parent and the child. The parent executes into
+<em>prog...</em>; the child remains and waits for a
+command. </li>
+ <li> At any time, <em>prog...</em> can send a command to its
+control socket provided by s6-ucspitlsc, following the
+<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
+protocol. Then the s6-ucspitlsc child will exec into a
+<a href="s6-tlsc-io.html">s6-tlsc-io</a>
+process that will initiate the TLS connection, perform the
+handshake (expecting a TLS server on the other side of the
+network) and maintain a TLS tunnel. <em>prog</em> can
+use that TLS tunnel instead of talking directly to the
+network. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 100: wrong usage. </li>
+ <li> 111: system call failed. </li>
+</ul>
+
+<p>
+ Normally the parent s6-ucspitlsc process execs into <em>prog...</em>
+and the child process execs into <a href="s6-tlsc-io.html">s6-tlsc-io</a>.
+If the parent dies or closes its control socket before sending a
+command to start TLS, the child exits 0.
+</p>
+
+<h2> Environment variables </h2>
+
+<h3> Read </h3>
+
+<p>
+ s6-ucspitlsc does not expect to have any particular
+environment variables, but it spawns a
+<a href="s6-tlsc-io.html">s6-tlsc-io</a> program that does.
+So it should pay attention to the following variables:
+</p>
+
+<ul>
+ <li> <tt>CADIR</tt> or <tt>CAFILE</tt> </li>
+ <li> (if the -y option has been given) <tt>CERTFILE</tt> and <tt>KEYFILE</tt> </li>
+ <li> <tt>TLS_UID</tt> and <tt>TLS_GID</tt>
+</ul>
+
+<h3> Written </h3>
+
+<p>
+ By default, <em>prog...</em> is run with all these
+variables <em>unset</em>: CADIR, CAFILE,
+KEYFILE, CERTFILE, TLS_UID and TLS_GID. They're passed to
+the <a href="s6-tlsc-io.html">s6-tlsc-io</a> child but
+not to <em>prog...</em>.
+The <tt>-Z</tt> option prevents that behaviour.
+</p>
+
+<p>
+ However, <em>prog...</em> is run with the following additional
+environment variables, following the UCSPI-TLS protocol:
+</p>
+
+<ul>
+ <li> <tt>SSLCTLFD</tt> contains the file descriptor number of
+the control socket. </li>
+ <li> <tt>SSLREADFD</tt> contains the file descriptor number of
+the pipe used to read data from the TLS tunnel after it
+has been activated. </li>
+ <li> <tt>SSLWRITEFD</tt> contains the file descriptor number of
+the pipe used to write data to the TLS tunnel after it
+has been activated. </li>
+</ul>
+
+<p>
+ Since <em>prog</em> is exec'ed before the TLS handshake takes
+place, it cannot get information about the TLS connection via
+environment variables. However, if it starts the TLS connection
+via a <tt>Y</tt> command (as opposed to a <tt>y</tt> command),
+it will receive this information as a string sent over the
+control socket.
+</p>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
+verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
+verbose, more than 2 is debug output. This option currently has
+no effect. </li>
+ <li> <tt>-Z</tt>&nbsp;: do not clean the environment of
+the variables used by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+before execing <em>prog...</em>. </li>
+ <li> <tt>-z</tt>&nbsp;: clean the environment of
+the variables used by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+before execing <em>prog...</em>. This is the default. </li>
+ <li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
+and break the connection when <em>prog</em> sends EOF. </li>
+ <li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
+connection without using <tt>close_notify</tt>. This is the default. </li>
+ <li> <tt>-Y</tt>&nbsp;: Do not send a client certificate. This is the default. </li>
+ <li> <tt>-y</tt>&nbsp;: Send a client certificate. </li>
+ <li> <tt>-k&nbsp;<em>servername</em></tt>&nbsp;: use Server Name
+Indication, and send <em>servername</em>. The default is not to
+use SNI, which may be a security risk. </li>
+ <li> <tt>-K&nbsp;<em>kimeout</em></tt>&nbsp;: close the connection
+if <em>kimeout</em> milliseconds elapse without any data being
+received from either side. The default is 0, which means
+infinite timeout (never kill the connection). </li>
+ <li> <tt>-6&nbsp;<em>fdr</em></tt>&nbsp;: expect an open file
+descriptor numbered <em>fdr</em> to read network (ciphertext)
+data from. Make sure <em>prog</em> also reads its data
+from its own fd <em>fdr</em>. Default is 6. </li>
+ <li> <tt>-7&nbsp;<em>fdw</em></tt>&nbsp;: expect an open file
+descriptor numbered <em>fdw</em> to write network (ciphertext)
+data to. Make sure <em>prog</em> also writes its data to
+its own fd <em>fdw</em>. Default is 7. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> It only makes sense to run s6-ucspitlsc if its application
+program <em>prog</em> knows and understands the
+<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
+protocol for opportunistic TLS. If it does not, you will not
+be able to secure your connection, and what you need is a regular
+immediate TLS program instead, which means
+<a href="s6-tlsc.html">s6-tlsc</a>. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/s6-ucspitlsd.html b/doc/s6-ucspitlsd.html
new file mode 100644
index 0000000..51372e2
--- /dev/null
+++ b/doc/s6-ucspitlsd.html
@@ -0,0 +1,168 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-networking: the s6-ucspitlsd program</title>
+ <meta name="Description" content="s6-networking: the s6-ucspitlsd program" />
+ <meta name="Keywords" content="s6-networking s6-ucspitlsd tlsd tls ssl ucspi ucspi-tls delayed encryption opportunistic tls tcp inet network tcp/ip client" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-networking</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-ucspitlsd</tt> program </h1>
+
+<p>
+<tt>s6-ucspitlsd</tt> is a server-side program that establishes
+communication channels according to the UCSPI-TLS protocol,
+then execs into an application. Later, if the application sends
+a command, a TLS tunnel will be started and the application will
+be able to use it instead of communicating with the network via
+cleartext.
+</p>
+
+<p>
+ The point of this protocol, and this program, is to make it easy
+to implement commands like SMTP's STARTTLS without embedding a
+TLS stack in the server itself.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-ucspitlsd [ -S | -s ] [ -Y | -y ] [ -Z | -z ] [ -v <em>verbosity</em> ] [ -K kimeout ] [ -- ] <em>prog...</em>
+</pre>
+
+<ul>
+ <li> s6-ucspitlsd expects to have an open TCP connection it
+can talk to on its stdin and stdout. </li>
+ <li> It forks and establishes communication channels between
+the parent and the child. The parent executes into
+<em>prog...</em>; the child remains and waits for a
+command. </li>
+ <li> At any time, <em>prog...</em> can send a command to its
+control socket provided by s6-ucspitlsd, following the
+<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
+protocol. Then the s6-ucspitlsd child will exec into a
+<a href="s6-tlsd-io.html">s6-tlsd-io</a>
+process that will initialize the TLS connection, perform the
+handshake (expecting a TLS client on the other side of the
+network) and maintain a TLS tunnel. <em>prog</em> can
+use that TLS tunnel instead of talking directly to the
+network. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 100: wrong usage. </li>
+ <li> 111: system call failed. </li>
+</ul>
+
+<p>
+ Normally the parent s6-ucspitlsd process execs into <em>prog...</em>
+and the child process execs into <a href="s6-tlsd-io.html">s6-tlsd-io</a>.
+If the parent dies or closes its control socket before sending a
+command to start TLS, the child exits 0.
+</p>
+
+<h2> Environment variables </h2>
+
+<h3> Read </h3>
+
+<p>
+ s6-ucspitlsd does not expect to have any particular
+environment variables, but it spawns a
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> program that does.
+So it should pay attention to the following variables:
+</p>
+
+<ul>
+ <li> <tt>CERTFILE</tt> and <tt>KEYFILE</tt> </li>
+ <li> (if the <tt>-Y</tt> or <tt>-y</tt> option has been given) <tt>CADIR</tt> or <tt>CAFILE</tt> </li>
+ <li> <tt>TLS_UID</tt> and <tt>TLS_GID</tt>
+</ul>
+
+<h3> Written </h3>
+
+<p>
+ By default, <em>prog...</em> is run with all these
+variables <em>unset</em>: CADIR, CAFILE,
+KEYFILE, CERTFILE, TLS_UID and TLS_GID. They're passed to
+the <a href="s6-tlsd-io.html">s6-tlsd-io</a> child but
+not to <em>prog...</em>.
+The <tt>-Z</tt> option prevents that behaviour.
+</p>
+
+<p>
+ However, <em>prog...</em> is run with the following additional
+environment variables, following the UCSPI-TLS protocol:
+</p>
+
+<ul>
+ <li> <tt>SSLCTLFD</tt> contains the file descriptor number of
+the control socket. </li>
+ <li> <tt>SSLREADFD</tt> contains the file descriptor number of
+the pipe used to read data from the TLS tunnel after it
+has been activated. </li>
+ <li> <tt>SSLWRITEFD</tt> contains the file descriptor number of
+the pipe used to write data to the TLS tunnel after it
+has been activated. </li>
+</ul>
+
+<p>
+ Since <em>prog</em> is exec'ed before the TLS handshake takes
+place, it cannot get information about the TLS connection via
+environment variables. However, if it starts the TLS connection
+via a <tt>Y</tt> command (as opposed to a <tt>y</tt> command),
+it will receive this information as a string sent over the
+control socket.
+</p>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: Be more or less
+verbose. Default for <em>verbosity</em> is 1. 0 is quiet, 2 is
+verbose, more than 2 is debug output. This option currently has
+no effect. </li>
+ <li> <tt>-Z</tt>&nbsp;: do not clean the environment of
+the variables used by <a href="s6-tlsc-io.html">s6-tlsc-io</a>
+before execing <em>prog...</em>. </li>
+ <li> <tt>-z</tt>&nbsp;: clean the environment of
+the variables used by <a href="s6-tlsd-io.html">s6-tlsd-io</a>
+before execing <em>prog...</em>. This is the default. </li>
+ <li> <tt>-S</tt>&nbsp;: send a <tt>close_notify</tt> alert
+and break the connection when <em>prog</em> sends EOF. </li>
+ <li> <tt>-s</tt>&nbsp;: transmit EOF by half-closing the TCP
+connection without using <tt>close_notify</tt>. This is the default. </li>
+ <li> <tt>-Y</tt>&nbsp;: Require an optional client certificate. </li>
+ <li> <tt>-y</tt>&nbsp;: Require a mandatory client certificate.
+The default, with neither the <tt>-Y</tt> nor the <tt>-y</tt> option,
+is not to require a client certificate at all. </li>
+ <li> <tt>-K&nbsp;<em>kimeout</em></tt>&nbsp;: close the connection
+if <em>kimeout</em> milliseconds elapse without any data being
+received from either side. The default is 0, which means
+infinite timeout (never kill the connection). </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> It only makes sense to run s6-ucspitlsd if its application
+program <em>prog</em> knows and understands the
+<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
+protocol for opportunistic TLS. If it does not, you will not
+be able to secure your connection, and what you need is a regular
+immediate TLS program instead, which means
+<a href="s6-tlsd.html">s6-tlsd</a>. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/tls-overview.html b/doc/tls-overview.html
new file mode 100644
index 0000000..4ba3f69
--- /dev/null
+++ b/doc/tls-overview.html
@@ -0,0 +1,142 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6-networking: an overview of the tls-related programs</title>
+ <meta name="Description" content="s6-networking: an overview of the tls-related programs" />
+ <meta name="Keywords" content="s6-networking s6-tlsc s6-tlsd tlsc tlsd tlsc-io ucspi-tls ucspi-ssl tlsd-io ssl ucspi tcp inet network tcp/ip client" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6-networking</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> An overview of the tls-related programs </h1>
+
+<p>
+ The <tt>s6-*tls*</tt> programs are organized in a way that minimizes
+the amount of code, and in particular that keeps the crypto code as
+encapsulated as possible.
+</p>
+
+<p>
+ They are divided in two sets: client programs, which have <tt>client</tt>
+or <tt>c</tt> in their name, and server programs, which have <tt>server</tt>
+or <tt>d</tt> in their name. The sets are symmetrical: the same
+functionality is available whether you're interested in using a
+client or a server.
+</p>
+
+<p>
+ Of course, they do not have to be used together. You can run a
+TLS-enabled super-server via <a href="s6-tlsserver.html">s6-tlsserver</a>
+and it will work with any client speaking the correct TLS-enabled
+protocol, not only <a href="s6-tlsclient.html">s6-tlsclient</a>.
+</p>
+
+<h2> The core TLS engine: s6-tlsc-io and s6-tlsd-io </h2>
+
+<ul>
+ <li> <a href="s6-tlsc-io.html">s6-tlsc-io</a> and
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> are the only programs
+that actually perform TLS operations; the only ones that are linked
+against the BearSSL or LibreSSL libraries. </li>
+ <li> They read TLS-related
+information (where to find my trust anchor list? where to find my
+server certificate and private key?) from their environment. </li>
+ <li> They assume that their stdin/stdout is talking to the network; they
+also take two other fds on the command line that they assume are
+open and talking to the local application - one for reading, one for
+writing. </li>
+ <li> They establish a TLS tunnel over the network. </li>
+ <li> They maintain full-duplex communication: what they read
+from the local application is sent to stdout as ciphertext; what
+they read from stdin is sent to the local application as cleartext. </li>
+ <li> They exit when they cannot transmit any more data. </li>
+</ul>
+
+<p>
+ Other programs in the s6-tls set perform various operations such as
+Unix file descriptor plumbing in order to provide a specific interface,
+but they always end up spawning a
+<a href="s6-tlsc-io.html">s6-tlsc-io</a> or
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> child that will handle the
+actual TLS management for them.
+</p>
+
+<h2> Regular TLSification of a service: s6-tlsc and s6-tlsd </h2>
+
+<ul>
+ <li> The <a href="s6-tlsc.html">s6-tlsc</a> and
+<a href="s6-tlsd.html">s6-tlsd</a> programs are "immediate encryption"-type
+programs. They assume that the rest of their command line is a
+UCSPI client or server application, i.e. reads from the network on
+fd (6 for clients, 0 for servers) and writes to the network on fd
+(7 for clients, 1 for servers); their goal is to provide this
+application with transparent encryption. </li>
+ <li> They first spawn a <a href="s6-tlsc-io.html">s6-tlsc-io</a> or
+<a href="s6-tlsd-io.html">s6-tlsd-io</a> child to initialize the TLS
+connection. </li>
+ <li> When the TLS handshake has completed, they exec into the
+rest of their command line, interposing the s6-tls[cd]-io program
+in between this application and the network. </li>
+ <li> The application still communicates via cleartext, but the
+data is transparently encrypted before it goes to the network. </li>
+ <li> The application is <em>only</em> started after the handshake
+succeeds; the TLS tunnel stays up for the whole lifetime of the
+application, or until the application closes the fds it uses to
+communicate with (what it thinks is) the network. </li>
+</ul>
+
+<h2> Opportunistic TLS: s6-ucspitlsc and s6-ucspitlsd </h2>
+
+<ul>
+ <li> The <a href="s6-ucspitlsc.html">s6-ucspitlsc</a> and
+<a href="s6-ucspitlsd.html">s6-ucspitlsd</a> programs are
+"delayed encryption"-type programs. They assume that the rest
+of their command line is an application that follows the
+<a href="https://web.archive.org/web/20150311223933/http://www.suspectclass.com/sgifford/ucspi-tls/ucspi-tls.txt">UCSPI-TLS</a>
+protocol. This is a bit of a misnomer: the aim of this protocol is
+just to provide an application with a means to ask for TLS
+encryption at any time. </li>
+ <li> They prepare the necessary communication channels, then
+fork. The parent execs into the rest of its command line, with
+the appropriate ucspi-tls environment variables set. The child
+stays and waits for a command. </li>
+ <li> When the application sends a command to start TLS, the
+child execs into <a href="s6-tlsc-io.html">s6-tlsc-io</a> or
+<a href="s6-tlsd-io.html">s6-tlsd-io</a>, which initializes
+a TLS connection and performs a handshake. </li>
+ <li> The application then communicates via the fds that have
+been provided to it via the ucspi-tls protocol. Those fds go
+through the TLS engine. </li>
+</ul>
+
+<h2> High-level client connections and super-servers: s6-tlsclient and s6-tlsserver </h2>
+
+<ul>
+ <li> The <a href="s6-tlsclient.html">s6-tlsclient</a> and
+<a href="s6-tlsserver.html">s6-tlsserver</a> programs are high-level
+wrappers around TCP client and server functionality, followed by the
+establishment of a TLS tunnel, followed by the execution of an
+application. They're meant to provide simpler interfaces over
+long, complex command lines. </li>
+ <li> <a href="s6-tlsclient.html">s6-tlsclient</a> rewrites itself
+into a command line involving
+<a href="s6-tcpclient.html">s6-tcpclient</a> and
+<a href="s6-tlsc.html">s6-tlsc</a>. </li>
+ <li> <a href="s6-tlsserver.html">s6-tlsserver</a> rewrites itself
+into a command line involving (depending on the given options)
+<a href="s6-tcpserver.html">s6-tcpserver</a>,
+<a href="s6-tcpserver.html">s6-tcpserver-access</a>,
+<a href="s6-tlsd.html">s6-tlsd</a>, and
+<a href="//skarnet.org/software/s6/s6-applyuidgid.html">s6-applyuidgid</a>. </li>
+</ul>
+
+</body>
+</html>
diff --git a/src/sbearssl/sbearssl_drop.c b/src/sbearssl/sbearssl_drop.c
index 2d826af..31e5f49 100644
--- a/src/sbearssl/sbearssl_drop.c
+++ b/src/sbearssl/sbearssl_drop.c
@@ -12,8 +12,8 @@ void sbearssl_drop (void)
{
if (!getuid())
{
- uid_t uid ;
- gid_t gid ;
+ uid_t uid = 0 ;
+ gid_t gid = 0 ;
char const *x = getenv("TLS_UID") ;
if (x && !uid0_scan(x, &uid)) strerr_dieinvalid(100, "TLS_UID") ;
x = getenv("TLS_GID") ;
diff --git a/src/stls/stls_drop.c b/src/stls/stls_drop.c
index d1e6831..7fc1bc5 100644
--- a/src/stls/stls_drop.c
+++ b/src/stls/stls_drop.c
@@ -12,8 +12,8 @@ void stls_drop (void)
{
if (!getuid())
{
- uid_t uid ;
- gid_t gid ;
+ uid_t uid = 0 ;
+ gid_t gid = 0 ;
char const *x = getenv("TLS_UID") ;
if (x && !uid0_scan(x, &uid)) strerr_dieinvalid(100, "TLS_UID") ;
x = getenv("TLS_GID") ;