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