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 \bog{}server\cog{} and \bog{}client\cog{} 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