1%%
2%%
3
4%\bauthors{Landon Fuller}
5%\title{Bacula TLS Additions}
6
7\chapter{TLS}
8\label{blb:TheChapter_TLS}
9\index{TLS}
10
11Written by Landon Fuller
12
13\section{Introduction to TLS}
14\index{TLS Introduction}
15\index{Introduction!TLS}
16
17This patch includes all the back-end code necessary to add complete TLS
18data encryption support to Bacula.  In addition, support for TLS in
19Console/Director communications has been added as a proof of concept.
20Adding support for the remaining daemons will be straight-forward.
21Supported features of this patchset include:
22
23\begin{bitemize}
24\item Client/Server TLS Requirement Negotiation
25\item TLSv1 Connections with Server and Client Certificate
26Validation
27\item Forward Secrecy Support via Diffie-Hellman Ephemeral Keying
28\end{bitemize}
29
30This document will refer to both ``server'' and ``client'' contexts.  These
31terms refer to the accepting and initiating peer, respectively.
32
33Diffie-Hellman anonymous ciphers are not supported by this patchset.  The
34use of DH anonymous ciphers increases the code complexity and places
35explicit trust upon the two-way Cram-MD5 implementation.  Cram-MD5 is
36subject to known plaintext attacks, and is should be considered
37considerably less secure than PKI certificate-based authentication.
38
39Appropriate autoconf macros have been added to detect and use OpenSSL. Two
40additional preprocessor defines have been added: \emph{HAVE\_TLS} and
41\emph{HAVE\_OPENSSL}.  All changes not specific to OpenSSL rely on
42\emph{HAVE\_TLS}.  OpenSSL-specific code is constrained to
43\emph{src/lib/tls.c} to facilitate the support of alternative TLS
44implementations.
45
46\section{New Configuration Directives}
47\index{TLS Configuration Directives}
48\index{Directives!TLS Configuration}
49
50Additional configuration directives have been added to both the Console and
51Director resources.  These new directives are defined as follows:
52
53\begin{bitemize}
54\item \underline{TLS Enable} \emph{(yes/no)}
55Enable TLS support.
56
57\item \underline{TLS Require} \emph{(yes/no)}
58Require TLS connections.
59
60\item \underline{TLS Certificate} \emph{(path)}
61Path to PEM encoded TLS certificate.  Used as either a client or server
62certificate.
63
64\item \underline{TLS Key} \emph{(path)}
65Path to PEM encoded TLS private key.  Must correspond with the TLS
66certificate.
67
68\item \underline{TLS Verify Peer} \emph{(yes/no)}
69Verify peer certificate.  Instructs server to request and verify the
70client's x509 certificate.  Any client certificate signed by a known-CA
71will be accepted unless the TLS Allowed CN configuration directive is used.
72Not valid in a client context.
73
74\item \underline{TLS Allowed CN} \emph{(string list)}
75Common name attribute of allowed peer certificates.  If directive is
76specified, all client certificates will be verified against this list.
77This directive may be specified more than once.  Not valid in a client
78context.
79
80\item \underline{TLS CA Certificate File} \emph{(path)}
81Path to PEM encoded TLS CA certificate(s).  Multiple certificates are
82permitted in the file.  One of \emph{TLS CA Certificate File} or \emph{TLS
83CA Certificate Dir} are required in a server context if \underline{TLS
84Verify Peer} is also specified, and are always required in a client
85context.
86
87\item \underline{TLS CA Certificate Dir} \emph{(path)}
88Path to TLS CA certificate directory.  In the current implementation,
89certificates must be stored PEM encoded with OpenSSL-compatible hashes.
90One of \emph{TLS CA Certificate File} or \emph{TLS CA Certificate Dir} are
91required in a server context if \emph{TLS Verify Peer} is also specified,
92and are always required in a client context.
93
94\item \underline{TLS DH File} \emph{(path)}
95Path to PEM encoded Diffie-Hellman parameter file.  If this directive is
96specified, DH ephemeral keying will be enabled, allowing for forward
97secrecy of communications.  This directive is only valid within a server
98context.  To generate the parameter file, you may use openssl:
99\footnotesize
100\begin{bVerbatim}
101openssl dhparam -out dh1024.pem -5 1024
102\end{bVerbatim}
103\normalsize
104\end{bitemize}
105
106\section{TLS API Implementation}
107\index{TLS API Implimentation}
108\index{API Implimentation!TLS}
109
110To facilitate the use of additional TLS libraries, all OpenSSL-specific
111code has been implemented within \emph{src/lib/tls.c}.  In turn, a generic
112TLS API is exported.
113
114\subsection{Library Initialization and Cleanup}
115\index{Library Initialization and Cleanup}
116\index{Initialization and Cleanup!Library}
117
118\footnotesize
119\begin{bVerbatim}
120int init_tls (void);
121\end{bVerbatim}
122\normalsize
123
124Performs TLS library initialization, including seeding of the PRNG. PRNG
125seeding has not yet been implemented for win32.
126
127\footnotesize
128\begin{bVerbatim}
129int cleanup_tls (void);
130\end{bVerbatim}
131\normalsize
132
133Performs TLS library cleanup.
134
135\subsection{Manipulating TLS Contexts}
136\index{TLS Context Manipulation}
137\index{Contexts!Manipulating TLS}
138
139\footnotesize
140\begin{bVerbatim}
141TLS_CONTEXT  *new_tls_context (const char *ca_certfile,
142        const char *ca_certdir, const char *certfile,
143        const char *keyfile, const char *dhfile, bool verify_peer);
144\end{bVerbatim}
145\normalsize
146
147Allocates and initalizes a new opaque \emph{TLS\_CONTEXT} structure.  The
148\emph{TLS\_CONTEXT} structure maintains default TLS settings from which
149\emph{TLS\_CONNECTION} structures are instantiated.  In the future the
150\emph{TLS\_CONTEXT} structure may be used to maintain the TLS session
151cache.  \emph{ca\_certfile} and \emph{ca\_certdir} arguments are used to
152initialize the CA verification stores.  The \emph{certfile} and
153\emph{keyfile} arguments are used to initialize the local certificate and
154private key.  If \emph{dhfile} is non-NULL, it is used to initialize
155Diffie-Hellman ephemeral keying.  If \emph{verify\_peer} is \emph{true} ,
156client certificate validation is enabled.
157
158\footnotesize
159\begin{bVerbatim}
160void free_tls_context (TLS_CONTEXT *ctx);
161\end{bVerbatim}
162\normalsize
163
164Deallocated a previously allocated \emph{TLS\_CONTEXT} structure.
165
166\subsection{Performing Post-Connection Verification}
167\index{TLS Post-Connection Verification}
168\index{Verification!TLS Post-Connection}
169
170\footnotesize
171\begin{bVerbatim}
172bool tls_postconnect_verify_host (TLS_CONNECTION *tls, const char *host);
173\end{bVerbatim}
174\normalsize
175
176Performs post-connection verification of the peer-supplied x509
177certificate.  Checks whether the \emph{subjectAltName} and
178\emph{commonName} attributes match the supplied \emph{host} string.
179Returns \emph{true} if there is a match, \emph{false} otherwise.
180
181\footnotesize
182\begin{bVerbatim}
183bool tls_postconnect_verify_cn (TLS_CONNECTION *tls, alist *verify_list);
184\end{bVerbatim}
185\normalsize
186
187Performs post-connection verification of the peer-supplied x509
188certificate.  Checks whether the \emph{commonName} attribute matches any
189strings supplied via the \emph{verify\_list} parameter.  Returns
190\emph{true} if there is a match, \emph{false} otherwise.
191
192\subsection{Manipulating TLS Connections}
193\index{TLS Connection Manipulation}
194\index{Connections!Manipulating TLS}
195
196\footnotesize
197\begin{bVerbatim}
198TLS_CONNECTION *new_tls_connection (TLS_CONTEXT *ctx, int fd);
199\end{bVerbatim}
200\normalsize
201
202Allocates and initializes a new \emph{TLS\_CONNECTION} structure with
203context \emph{ctx} and file descriptor \emph{fd}.
204
205\footnotesize
206\begin{bVerbatim}
207void free_tls_connection (TLS_CONNECTION *tls);
208\end{bVerbatim}
209\normalsize
210
211Deallocates memory associated with the \emph{tls} structure.
212
213\footnotesize
214\begin{bVerbatim}
215bool tls_bsock_connect (BSOCK *bsock);
216\end{bVerbatim}
217\normalsize
218
219Negotiates a a TLS client connection via \emph{bsock}.  Returns \emph{true}
220if successful, \emph{false} otherwise.  Will fail if there is a TLS
221protocol error or an invalid certificate is presented
222
223\footnotesize
224\begin{bVerbatim}
225bool tls_bsock_accept (BSOCK *bsock);
226\end{bVerbatim}
227\normalsize
228
229Accepts a TLS client connection via \emph{bsock}.  Returns \emph{true} if
230successful, \emph{false} otherwise.  Will fail if there is a TLS protocol
231error or an invalid certificate is presented.
232
233\footnotesize
234\begin{bVerbatim}
235bool tls_bsock_shutdown (BSOCK *bsock);
236\end{bVerbatim}
237\normalsize
238
239Issues a blocking TLS shutdown request to the peer via \emph{bsock}. This function may not wait for the peer's reply.
240
241\footnotesize
242\begin{bVerbatim}
243int tls_bsock_writen (BSOCK *bsock, char *ptr, int32_t nbytes);
244\end{bVerbatim}
245\normalsize
246
247Writes \emph{nbytes} from \emph{ptr} via the \emph{TLS\_CONNECTION}
248associated with \emph{bsock}.  Due to OpenSSL's handling of \emph{EINTR},
249\emph{bsock} is set non-blocking at the start of the function, and restored
250to its original blocking state before the function returns.  Less than
251\emph{nbytes} may be written if an error occurs.  The actual number of
252bytes written will be returned.
253
254\footnotesize
255\begin{bVerbatim}
256int tls_bsock_readn (BSOCK *bsock, char *ptr, int32_t nbytes);
257\end{bVerbatim}
258\normalsize
259
260Reads \emph{nbytes} from the \emph{TLS\_CONNECTION} associated with
261\emph{bsock} and stores the result in \emph{ptr}.  Due to OpenSSL's
262handling of \emph{EINTR}, \emph{bsock} is set non-blocking at the start of
263the function, and restored to its original blocking state before the
264function returns.  Less than \emph{nbytes} may be read if an error occurs.
265The actual number of bytes read will be returned.
266
267\section{Bnet API Changes}
268\index{Bnet API Changes}
269\index{API Changes!Bnet}
270
271A minimal number of changes were required in the Bnet socket API. The BSOCK
272structure was expanded to include an associated TLS\_CONNECTION structure,
273as well as a flag to designate the current blocking state of the socket.
274The blocking state flag is required for win32, where it does not appear
275possible to discern the current blocking state of a socket.
276
277\subsection{Negotiating a TLS Connection}
278\index{Negotiating a TLS Connection}
279\index{TLS Connection!Negotiating}
280
281\emph{bnet\_tls\_server()} and \emph{bnet\_tls\_client()} were both
282implemented using the new TLS API as follows:
283
284\footnotesize
285\begin{bVerbatim}
286int bnet_tls_client(TLS_CONTEXT *ctx, BSOCK * bsock);
287\end{bVerbatim}
288\normalsize
289
290Negotiates a TLS session via \emph{bsock} using the settings from
291\emph{ctx}.  Returns 1 if successful, 0 otherwise.
292
293\footnotesize
294\begin{bVerbatim}
295int bnet_tls_server(TLS_CONTEXT *ctx, BSOCK * bsock, alist *verify_list);
296\end{bVerbatim}
297\normalsize
298
299Accepts a TLS client session via \emph{bsock} using the settings from
300\emph{ctx}.  If \emph{verify\_list} is non-NULL, it is passed to
301\emph{tls\_postconnect\_verify\_cn()} for client certificate verification.
302
303\subsection{Manipulating Socket Blocking State}
304\index{Manipulating Socket Blocking State}
305\index{Socket Blocking State!Manipulating}
306\index{Blocking State!Socket!Manipulating}
307
308Three functions were added for manipulating the blocking state of a socket
309on both Win32 and Unix-like systems.  The Win32 code was written according
310to the MSDN documentation, but has not been tested.
311
312These functions are prototyped as follows:
313
314\footnotesize
315\begin{bVerbatim}
316int bnet_set_nonblocking (BSOCK *bsock);
317\end{bVerbatim}
318\normalsize
319
320Enables non-blocking I/O on the socket associated with \emph{bsock}.
321Returns a copy of the socket flags prior to modification.
322
323\footnotesize
324\begin{bVerbatim}
325int bnet_set_blocking (BSOCK *bsock);
326\end{bVerbatim}
327\normalsize
328
329Enables blocking I/O on the socket associated with \emph{bsock}.  Returns a
330copy of the socket flags prior to modification.
331
332\footnotesize
333\begin{bVerbatim}
334void bnet_restore_blocking (BSOCK *bsock, int flags);
335\end{bVerbatim}
336\normalsize
337
338Restores blocking or non-blocking IO setting on the socket associated with
339\emph{bsock}.  The \emph{flags} argument must be the return value of either
340\emph{bnet\_set\_blocking()} or \emph{bnet\_restore\_blocking()}.
341
342\pagebreak
343
344\section{Authentication Negotiation}
345\index{Authentication Negotiation}
346\index{Negotiation!TLS Authentication}
347
348Backwards compatibility with the existing SSL negotiation hooks implemented
349in src/lib/cram-md5.c have been maintained.  The
350\emph{cram\_md5\_get\_auth()} function has been modified to accept an
351integer pointer argument, tls\_remote\_need.  The TLS requirement
352advertised by the remote host is returned via this pointer.
353
354After exchanging cram-md5 authentication and TLS requirements, both the
355client and server independently decide whether to continue:
356
357\footnotesize
358\begin{bVerbatim}
359if (!cram_md5_get_auth(dir, password, &tls_remote_need) ||
360        !cram_md5_auth(dir, password, tls_local_need)) {
361[snip]
362/* Verify that the remote host is willing to meet our TLS requirements */
363if (tls_remote_need < tls_local_need && tls_local_need != BNET_TLS_OK &&
364        tls_remote_need != BNET_TLS_OK) {
365   sendit(_("Authorization problem:"
366            " Remote server did not advertise required TLS support.\n"));
367   auth_success = false;
368   goto auth_done;
369}
370
371/* Verify that we are willing to meet the remote host's requirements */
372if (tls_remote_need > tls_local_need && tls_local_need != BNET_TLS_OK &&
373        tls_remote_need != BNET_TLS_OK) {
374   sendit(_("Authorization problem:"
375            " Remote server requires TLS.\n"));
376   auth_success = false;
377   goto auth_done;
378}
379\end{bVerbatim}
380\normalsize
381