1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
<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 stls library interface</title>
<meta name="Description" content="s6-networking: the stls library interface" />
<meta name="Keywords" content="s6-networking net stls library TLS SSL LibreSSL OpenSSL libtls" />
<!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
</head>
<body>
<p>
<a href="../">s6-networking</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>
<h1> The <tt>stls</tt> library interface </h1>
<h2> General information </h2>
<p>
<tt>libstls</tt> is a small support library for the
<a href="../s6-tlsc.html">s6-tlsc</a> and
<a href="../s6-tlsd.html">s6-tlsd</a> executables when they're built
against the <em>libtls</em> API, whether that API is implemented via
<a href="https://libressl.org/">LibreSSL</a> or via
<a href="https://openssl.org/">OpenSSL</a> with the addition of
<a href="https://git.causal.agency/libretls/about/">LibreTLS</a>.
You can use it in your own programs, but since
<a href="https://man.openbsd.org/OpenBSD-current/man3/tls_init.3">libtls</a>
is already relatively high-level, it's probably not very useful.
</p>
<h2> Compiling </h2>
<ul>
<li> Make sure the s6-networking headers, as well as the skalibs headers,
and the <tt>tls.h</tt> header, are visible in your header search path. </li>
<li> Use <tt>#include <s6-networking/stls.h></tt> </li>
</ul>
<h2> Linking </h2>
<ul>
<li> Make sure the s6-networking libraries, as well as the skalibs
libraries, and the libraries needed by libtls, are visible in your
library search path. </li>
<li> Link against <tt>-lstls</tt>, <tt>-lskarnet</tt>, <tt>-ltls</tt>,
<tt>-lssl</tt>, <tt>-lcrypto</tt>,
<tt>`cat $sysdeps/socket.lib`</tt>, <tt>`cat $sysdeps/spawn.lib`</tt>, and
<tt>`cat $sysdeps/sysclock.lib`</tt>, where <tt>$sysdeps</tt> is your skalibs
sysdeps directory. </li>
</ul>
<h2> Programming </h2>
<h3> Utilities </h3>
<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>
<h4> <code> int stls_send_environment (struct tls *ctx, int fd) </code> </h4>
<p>
Writes a series of null-terminated strings of the form <tt>key=value</tt>
to file descriptor <em>fd</em>; the series is terminated with an additional
null character. The strings represent information about the TLS connection
represented by context <em>ctx</em>; it is only valid to call this function
after the handshake has completed. The exact keys used will change over time,
but at least <tt>SSL_PROTOCOL=value</tt> and <tt>SSL_CIPHER=value</tt> are
transmitted. The function returns 1 if it succeeds and 0 if it fails.
</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> : an array of 2 file descriptors, that are in this
order: the fd reading from the network, the fd writing to the network. </li>
<li> <tt>preoptions</tt> : 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> : 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). 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 4 file descriptors, in this
order: fd reading clear text, fd writing clear text, fd reading
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.
<ul>
<li> bit 0 tells the engine how to behave when
the local application closes the connection (i.e. when the engine
reads EOF on <em>fds</em>[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. </li>
<li> bit 1 tells the engine whether (if set) or not (if clear) to
be sensitive to close_notify if on the <em>receiving</em> side of them.
If set, if the peer closes the connection without sending a close_notify,
the process will exit 98 with a fatal error message. If clear, the EOF
will be transmitted and the engine will continue serving the other half
of the connection until it's closed as well, and the process wil exit 0. </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> & 1</tt>).
You can use <tt>&tain_infinite_relative</tt> as a value for <em>tto</em>
if you don't want the engine to ever timeout. </li>
</ul>
<p>
<tt>stls_run</tt> 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.
</p>
</body>
</html>
|