blob: 4fb984f279b849e5aa864d4d3141fb37609ec150 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020046#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010047#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020048#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000056#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020057#endif
Emeric Brun46591952012-05-18 15:47:34 +020058
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020059#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000060#include <openssl/async.h>
61#endif
62
Christopher Faulet31af49d2015-06-09 17:29:50 +020063#include <import/lru.h>
64#include <import/xxhash.h>
65
Emeric Brun46591952012-05-18 15:47:34 +020066#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020067#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020068#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020094#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020095#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020096#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010097#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020098#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020099#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +0200100#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200101#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200102#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200103#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200104#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200105#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200106#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200107#include <proto/task.h>
108
Willy Tarreau518cedd2014-02-17 15:43:01 +0100109/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200110#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100111#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100112#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200113#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
114
Emeric Brunf282a812012-09-21 15:27:54 +0200115/* bits 0xFFFF0000 are reserved to store verify errors */
116
117/* Verify errors macros */
118#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
119#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
120#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
121
122#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
123#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
124#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200125
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100126/* Supported hash function for TLS tickets */
127#ifdef OPENSSL_NO_SHA256
128#define HASH_FUNCT EVP_sha1
129#else
130#define HASH_FUNCT EVP_sha256
131#endif /* OPENSSL_NO_SHA256 */
132
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200133/* ssl_methods flags for ssl options */
134#define MC_SSL_O_ALL 0x0000
135#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
136#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
137#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
138#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200139#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200140
141/* ssl_methods versions */
142enum {
143 CONF_TLSV_NONE = 0,
144 CONF_TLSV_MIN = 1,
145 CONF_SSLV3 = 1,
146 CONF_TLSV10 = 2,
147 CONF_TLSV11 = 3,
148 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200149 CONF_TLSV13 = 5,
150 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200151};
152
Emeric Brun850efd52014-01-29 12:24:34 +0100153/* server and bind verify method, it uses a global value as default */
154enum {
155 SSL_SOCK_VERIFY_DEFAULT = 0,
156 SSL_SOCK_VERIFY_REQUIRED = 1,
157 SSL_SOCK_VERIFY_OPTIONAL = 2,
158 SSL_SOCK_VERIFY_NONE = 3,
159};
160
William Lallemand3f85c9a2017-10-09 16:30:50 +0200161
Willy Tarreau71b734c2014-01-28 15:19:44 +0100162int sslconns = 0;
163int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100164static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100165int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200166
Willy Tarreauef934602016-12-22 23:12:01 +0100167static struct {
168 char *crt_base; /* base directory path for certificates */
169 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200174#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100189} global_ssl = {
190#ifdef LISTEN_DEFAULT_CIPHERS
191 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
192#endif
193#ifdef CONNECT_DEFAULT_CIPHERS
194 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
195#endif
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200196#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
197#ifdef LISTEN_DEFAULT_CIPHERSUITES
198 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
199#endif
200#ifdef CONNECT_DEFAULT_CIPHERSUITES
201 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
202#endif
203#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100204 .listen_default_ssloptions = BC_SSL_O_NONE,
205 .connect_default_ssloptions = SRV_SSL_O_NONE,
206
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200207 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
208 .listen_default_sslmethods.min = CONF_TLSV_NONE,
209 .listen_default_sslmethods.max = CONF_TLSV_NONE,
210 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
211 .connect_default_sslmethods.min = CONF_TLSV_NONE,
212 .connect_default_sslmethods.max = CONF_TLSV_NONE,
213
Willy Tarreauef934602016-12-22 23:12:01 +0100214#ifdef DEFAULT_SSL_MAX_RECORD
215 .max_record = DEFAULT_SSL_MAX_RECORD,
216#endif
217 .default_dh_param = SSL_DEFAULT_DH_PARAM,
218 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100219 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100220};
221
Emeric Brun821bb9b2017-06-15 16:37:39 +0200222#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100223
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224static HA_RWLOCK_T *ssl_rwlocks;
225
226
227unsigned long ssl_id_function(void)
228{
229 return (unsigned long)tid;
230}
231
232void ssl_locking_function(int mode, int n, const char * file, int line)
233{
234 if (mode & CRYPTO_LOCK) {
235 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100236 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200237 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100238 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200239 }
240 else {
241 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100242 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200243 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245 }
246}
247
248static int ssl_locking_init(void)
249{
250 int i;
251
252 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
253 if (!ssl_rwlocks)
254 return -1;
255
256 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100257 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200258
259 CRYPTO_set_id_callback(ssl_id_function);
260 CRYPTO_set_locking_callback(ssl_locking_function);
261
262 return 0;
263}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100264
Emeric Brun821bb9b2017-06-15 16:37:39 +0200265#endif
266
267
268
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100269/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100270struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100271 unsigned long long int xxh64;
272 unsigned char ciphersuite_len;
273 char ciphersuite[0];
274};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100275struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100276static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200277static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100278
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100279static int ssl_pkey_info_index = -1;
280
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200281#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
282struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
283#endif
284
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200285#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000286static unsigned int openssl_engines_initialized;
287struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
288struct ssl_engine_list {
289 struct list list;
290 ENGINE *e;
291};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200292#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000293
Remi Gacogne8de54152014-07-15 11:36:40 +0200294#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200295static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200296static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200297static DH *local_dh_1024 = NULL;
298static DH *local_dh_2048 = NULL;
299static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100300static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200301#endif /* OPENSSL_NO_DH */
302
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100303#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200304/* X509V3 Extensions that will be added on generated certificates */
305#define X509V3_EXT_SIZE 5
306static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
307 "basicConstraints",
308 "nsComment",
309 "subjectKeyIdentifier",
310 "authorityKeyIdentifier",
311 "keyUsage",
312};
313static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
314 "CA:FALSE",
315 "\"OpenSSL Generated Certificate\"",
316 "hash",
317 "keyid,issuer:always",
318 "nonRepudiation,digitalSignature,keyEncipherment"
319};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200320/* LRU cache to store generated certificate */
321static struct lru64_head *ssl_ctx_lru_tree = NULL;
322static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200323static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100324__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200325
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200326#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
327
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100328static struct ssl_bind_kw ssl_bind_kws[];
329
yanbzhube2774d2015-12-10 15:07:30 -0500330#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
331/* The order here matters for picking a default context,
332 * keep the most common keytype at the bottom of the list
333 */
334const char *SSL_SOCK_KEYTYPE_NAMES[] = {
335 "dsa",
336 "ecdsa",
337 "rsa"
338};
339#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100340#else
341#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500342#endif
343
William Lallemandc3cd35f2017-11-28 11:04:43 +0100344static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100345static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
346
347#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
348
349#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
350 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
351
352#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
353 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200354
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100355/*
356 * This function gives the detail of the SSL error. It is used only
357 * if the debug mode and the verbose mode are activated. It dump all
358 * the SSL error until the stack was empty.
359 */
360static forceinline void ssl_sock_dump_errors(struct connection *conn)
361{
362 unsigned long ret;
363
364 if (unlikely(global.mode & MODE_DEBUG)) {
365 while(1) {
366 ret = ERR_get_error();
367 if (ret == 0)
368 return;
369 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200370 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100371 ERR_func_error_string(ret), ERR_reason_error_string(ret));
372 }
373 }
374}
375
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200376#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500377/*
378 * struct alignment works here such that the key.key is the same as key_data
379 * Do not change the placement of key_data
380 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200381struct certificate_ocsp {
382 struct ebmb_node key;
383 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200384 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200385 long expire;
386};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200387
yanbzhube2774d2015-12-10 15:07:30 -0500388struct ocsp_cbk_arg {
389 int is_single;
390 int single_kt;
391 union {
392 struct certificate_ocsp *s_ocsp;
393 /*
394 * m_ocsp will have multiple entries dependent on key type
395 * Entry 0 - DSA
396 * Entry 1 - ECDSA
397 * Entry 2 - RSA
398 */
399 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
400 };
401};
402
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200403#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000404static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
405{
406 int err_code = ERR_ABORT;
407 ENGINE *engine;
408 struct ssl_engine_list *el;
409
410 /* grab the structural reference to the engine */
411 engine = ENGINE_by_id(engine_id);
412 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100413 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000414 goto fail_get;
415 }
416
417 if (!ENGINE_init(engine)) {
418 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100419 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000420 goto fail_init;
421 }
422
423 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100424 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000425 goto fail_set_method;
426 }
427
428 el = calloc(1, sizeof(*el));
429 el->e = engine;
430 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100431 nb_engines++;
432 if (global_ssl.async)
433 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000434 return 0;
435
436fail_set_method:
437 /* release the functional reference from ENGINE_init() */
438 ENGINE_finish(engine);
439
440fail_init:
441 /* release the structural reference from ENGINE_by_id() */
442 ENGINE_free(engine);
443
444fail_get:
445 return err_code;
446}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200447#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000448
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200449#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200450/*
451 * openssl async fd handler
452 */
453static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000454{
455 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456
Emeric Brun3854e012017-05-17 20:42:48 +0200457 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000458 * to poll this fd until it is requested
459 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000460 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000461 fd_cant_recv(fd);
462
463 /* crypto engine is available, let's notify the associated
464 * connection that it can pursue its processing.
465 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000466 __conn_sock_want_recv(conn);
467 __conn_sock_want_send(conn);
468 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000469}
470
Emeric Brun3854e012017-05-17 20:42:48 +0200471/*
472 * openssl async delayed SSL_free handler
473 */
474static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000475{
476 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200477 OSSL_ASYNC_FD all_fd[32];
478 size_t num_all_fds = 0;
479 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000480
Emeric Brun3854e012017-05-17 20:42:48 +0200481 /* We suppose that the async job for a same SSL *
482 * are serialized. So if we are awake it is
483 * because the running job has just finished
484 * and we can remove all async fds safely
485 */
486 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
487 if (num_all_fds > 32) {
488 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
489 return;
490 }
491
492 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
493 for (i=0 ; i < num_all_fds ; i++)
494 fd_remove(all_fd[i]);
495
496 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000497 SSL_free(ssl);
Emeric Brun7ad43e72018-10-10 14:51:02 +0200498 HA_ATOMIC_SUB(&sslconns, 1);
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200499 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000500}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501/*
Emeric Brun3854e012017-05-17 20:42:48 +0200502 * function used to manage a returned SSL_ERROR_WANT_ASYNC
503 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000504 */
Emeric Brun3854e012017-05-17 20:42:48 +0200505static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000506{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100507 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200508 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000509 size_t num_add_fds = 0;
510 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200511 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000512
513 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
514 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200515 if (num_add_fds > 32 || num_del_fds > 32) {
516 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517 return;
518 }
519
Emeric Brun3854e012017-05-17 20:42:48 +0200520 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521
Emeric Brun3854e012017-05-17 20:42:48 +0200522 /* We remove unused fds from the fdtab */
523 for (i=0 ; i < num_del_fds ; i++)
524 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000525
Emeric Brun3854e012017-05-17 20:42:48 +0200526 /* We add new fds to the fdtab */
527 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100528 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000529 }
530
Emeric Brun3854e012017-05-17 20:42:48 +0200531 num_add_fds = 0;
532 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
533 if (num_add_fds > 32) {
534 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
535 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536 }
Emeric Brun3854e012017-05-17 20:42:48 +0200537
538 /* We activate the polling for all known async fds */
539 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000540 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200541 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000542 /* To ensure that the fd cache won't be used
543 * We'll prefer to catch a real RD event
544 * because handling an EAGAIN on this fd will
545 * result in a context switch and also
546 * some engines uses a fd in blocking mode.
547 */
548 fd_cant_recv(add_fd[i]);
549 }
Emeric Brun3854e012017-05-17 20:42:48 +0200550
551 /* We must also prevent the conn_handler
552 * to be called until a read event was
553 * polled on an async fd
554 */
555 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000556}
557#endif
558
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200559/*
560 * This function returns the number of seconds elapsed
561 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
562 * date presented un ASN1_GENERALIZEDTIME.
563 *
564 * In parsing error case, it returns -1.
565 */
566static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
567{
568 long epoch;
569 char *p, *end;
570 const unsigned short month_offset[12] = {
571 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
572 };
573 int year, month;
574
575 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
576
577 p = (char *)d->data;
578 end = p + d->length;
579
580 if (end - p < 4) return -1;
581 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
582 p += 4;
583 if (end - p < 2) return -1;
584 month = 10 * (p[0] - '0') + p[1] - '0';
585 if (month < 1 || month > 12) return -1;
586 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
587 We consider leap years and the current month (<marsh or not) */
588 epoch = ( ((year - 1970) * 365)
589 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
590 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
591 + month_offset[month-1]
592 ) * 24 * 60 * 60;
593 p += 2;
594 if (end - p < 2) return -1;
595 /* Add the number of seconds of completed days of current month */
596 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
597 p += 2;
598 if (end - p < 2) return -1;
599 /* Add the completed hours of the current day */
600 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
601 p += 2;
602 if (end - p < 2) return -1;
603 /* Add the completed minutes of the current hour */
604 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
605 p += 2;
606 if (p == end) return -1;
607 /* Test if there is available seconds */
608 if (p[0] < '0' || p[0] > '9')
609 goto nosec;
610 if (end - p < 2) return -1;
611 /* Add the seconds of the current minute */
612 epoch += 10 * (p[0] - '0') + p[1] - '0';
613 p += 2;
614 if (p == end) return -1;
615 /* Ignore seconds float part if present */
616 if (p[0] == '.') {
617 do {
618 if (++p == end) return -1;
619 } while (p[0] >= '0' && p[0] <= '9');
620 }
621
622nosec:
623 if (p[0] == 'Z') {
624 if (end - p != 1) return -1;
625 return epoch;
626 }
627 else if (p[0] == '+') {
628 if (end - p != 5) return -1;
629 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700630 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200631 }
632 else if (p[0] == '-') {
633 if (end - p != 5) return -1;
634 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700635 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200636 }
637
638 return -1;
639}
640
Emeric Brun1d3865b2014-06-20 15:37:32 +0200641static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200642
643/* This function starts to check if the OCSP response (in DER format) contained
644 * in chunk 'ocsp_response' is valid (else exits on error).
645 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
646 * contained in the OCSP Response and exits on error if no match.
647 * If it's a valid OCSP Response:
648 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
649 * pointed by 'ocsp'.
650 * If 'ocsp' is NULL, the function looks up into the OCSP response's
651 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
652 * from the response) and exits on error if not found. Finally, If an OCSP response is
653 * already present in the container, it will be overwritten.
654 *
655 * Note: OCSP response containing more than one OCSP Single response is not
656 * considered valid.
657 *
658 * Returns 0 on success, 1 in error case.
659 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200660static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
661 struct certificate_ocsp *ocsp,
662 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200663{
664 OCSP_RESPONSE *resp;
665 OCSP_BASICRESP *bs = NULL;
666 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200667 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200668 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200669 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200670 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200671 int reason;
672 int ret = 1;
673
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200674 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
675 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200676 if (!resp) {
677 memprintf(err, "Unable to parse OCSP response");
678 goto out;
679 }
680
681 rc = OCSP_response_status(resp);
682 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
683 memprintf(err, "OCSP response status not successful");
684 goto out;
685 }
686
687 bs = OCSP_response_get1_basic(resp);
688 if (!bs) {
689 memprintf(err, "Failed to get basic response from OCSP Response");
690 goto out;
691 }
692
693 count_sr = OCSP_resp_count(bs);
694 if (count_sr > 1) {
695 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
696 goto out;
697 }
698
699 sr = OCSP_resp_get0(bs, 0);
700 if (!sr) {
701 memprintf(err, "Failed to get OCSP single response");
702 goto out;
703 }
704
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200705 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
706
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200708 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200709 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200710 goto out;
711 }
712
Emeric Brun13a6b482014-06-20 15:44:34 +0200713 if (!nextupd) {
714 memprintf(err, "OCSP single response: missing nextupdate");
715 goto out;
716 }
717
Emeric Brunc8b27b62014-06-19 14:16:17 +0200718 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200719 if (!rc) {
720 memprintf(err, "OCSP single response: no longer valid.");
721 goto out;
722 }
723
724 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200725 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200726 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
727 goto out;
728 }
729 }
730
731 if (!ocsp) {
732 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
733 unsigned char *p;
734
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200735 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200736 if (!rc) {
737 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
738 goto out;
739 }
740
741 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
742 memprintf(err, "OCSP single response: Certificate ID too long");
743 goto out;
744 }
745
746 p = key;
747 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200748 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200749 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
750 if (!ocsp) {
751 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
752 goto out;
753 }
754 }
755
756 /* According to comments on "chunk_dup", the
757 previous chunk buffer will be freed */
758 if (!chunk_dup(&ocsp->response, ocsp_response)) {
759 memprintf(err, "OCSP response: Memory allocation error");
760 goto out;
761 }
762
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200763 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
764
Emeric Brun4147b2e2014-06-16 18:36:30 +0200765 ret = 0;
766out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100767 ERR_clear_error();
768
Emeric Brun4147b2e2014-06-16 18:36:30 +0200769 if (bs)
770 OCSP_BASICRESP_free(bs);
771
772 if (resp)
773 OCSP_RESPONSE_free(resp);
774
775 return ret;
776}
777/*
778 * External function use to update the OCSP response in the OCSP response's
779 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
780 * to update in DER format.
781 *
782 * Returns 0 on success, 1 in error case.
783 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200784int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200785{
786 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
787}
788
789/*
790 * This function load the OCSP Resonse in DER format contained in file at
791 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
792 *
793 * Returns 0 on success, 1 in error case.
794 */
795static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
796{
797 int fd = -1;
798 int r = 0;
799 int ret = 1;
800
801 fd = open(ocsp_path, O_RDONLY);
802 if (fd == -1) {
803 memprintf(err, "Error opening OCSP response file");
804 goto end;
805 }
806
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200807 trash.data = 0;
808 while (trash.data < trash.size) {
809 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200810 if (r < 0) {
811 if (errno == EINTR)
812 continue;
813
814 memprintf(err, "Error reading OCSP response from file");
815 goto end;
816 }
817 else if (r == 0) {
818 break;
819 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200820 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200821 }
822
823 close(fd);
824 fd = -1;
825
826 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
827end:
828 if (fd != -1)
829 close(fd);
830
831 return ret;
832}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100833#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200834
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100835#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
836static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
837{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100838 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100839 struct tls_sess_key *keys;
840 struct connection *conn;
841 int head;
842 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100843 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100844
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200845 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200846 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100847 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
848
849 keys = ref->tlskeys;
850 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100851
852 if (enc) {
853 memcpy(key_name, keys[head].name, 16);
854
855 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100856 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857
858 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100859 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100860
861 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100862 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100863 } else {
864 for (i = 0; i < TLS_TICKETS_NO; i++) {
865 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
866 goto found;
867 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100868 ret = 0;
869 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100870
Christopher Faulet16f45c82018-02-16 11:23:49 +0100871 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100872 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
873 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100874 goto end;
875
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100876 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100877 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100878 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100879 end:
880 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
881 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200882}
883
884struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
885{
886 struct tls_keys_ref *ref;
887
888 list_for_each_entry(ref, &tlskeys_reference, list)
889 if (ref->filename && strcmp(filename, ref->filename) == 0)
890 return ref;
891 return NULL;
892}
893
894struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
895{
896 struct tls_keys_ref *ref;
897
898 list_for_each_entry(ref, &tlskeys_reference, list)
899 if (ref->unique_id == unique_id)
900 return ref;
901 return NULL;
902}
903
Willy Tarreau83061a82018-07-13 11:56:34 +0200904void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
905 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100906{
907 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200908 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
909 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100910 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
911 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
912}
913
Willy Tarreau83061a82018-07-13 11:56:34 +0200914int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100915{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200916 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
917
918 if(!ref) {
919 memprintf(err, "Unable to locate the referenced filename: %s", filename);
920 return 1;
921 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100922 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200923 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100924}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200925
926/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100927 * automatic ids. It's called just after the basic checks. It returns
928 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200929 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100930static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200931{
932 int i = 0;
933 struct tls_keys_ref *ref, *ref2, *ref3;
934 struct list tkr = LIST_HEAD_INIT(tkr);
935
936 list_for_each_entry(ref, &tlskeys_reference, list) {
937 if (ref->unique_id == -1) {
938 /* Look for the first free id. */
939 while (1) {
940 list_for_each_entry(ref2, &tlskeys_reference, list) {
941 if (ref2->unique_id == i) {
942 i++;
943 break;
944 }
945 }
946 if (&ref2->list == &tlskeys_reference)
947 break;
948 }
949
950 /* Uses the unique id and increment it for the next entry. */
951 ref->unique_id = i;
952 i++;
953 }
954 }
955
956 /* This sort the reference list by id. */
957 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
958 LIST_DEL(&ref->list);
959 list_for_each_entry(ref3, &tkr, list) {
960 if (ref->unique_id < ref3->unique_id) {
961 LIST_ADDQ(&ref3->list, &ref->list);
962 break;
963 }
964 }
965 if (&ref3->list == &tkr)
966 LIST_ADDQ(&tkr, &ref->list);
967 }
968
969 /* swap root */
970 LIST_ADD(&tkr, &tlskeys_reference);
971 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100972 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200973}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100974#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
975
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100976#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500977int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
978{
979 switch (evp_keytype) {
980 case EVP_PKEY_RSA:
981 return 2;
982 case EVP_PKEY_DSA:
983 return 0;
984 case EVP_PKEY_EC:
985 return 1;
986 }
987
988 return -1;
989}
990
Emeric Brun4147b2e2014-06-16 18:36:30 +0200991/*
992 * Callback used to set OCSP status extension content in server hello.
993 */
994int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
995{
yanbzhube2774d2015-12-10 15:07:30 -0500996 struct certificate_ocsp *ocsp;
997 struct ocsp_cbk_arg *ocsp_arg;
998 char *ssl_buf;
999 EVP_PKEY *ssl_pkey;
1000 int key_type;
1001 int index;
1002
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001003 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001004
1005 ssl_pkey = SSL_get_privatekey(ssl);
1006 if (!ssl_pkey)
1007 return SSL_TLSEXT_ERR_NOACK;
1008
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001009 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001010
1011 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1012 ocsp = ocsp_arg->s_ocsp;
1013 else {
1014 /* For multiple certs per context, we have to find the correct OCSP response based on
1015 * the certificate type
1016 */
1017 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1018
1019 if (index < 0)
1020 return SSL_TLSEXT_ERR_NOACK;
1021
1022 ocsp = ocsp_arg->m_ocsp[index];
1023
1024 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001025
1026 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001027 !ocsp->response.area ||
1028 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001029 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001030 return SSL_TLSEXT_ERR_NOACK;
1031
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001032 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001033 if (!ssl_buf)
1034 return SSL_TLSEXT_ERR_NOACK;
1035
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001036 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1037 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001038
1039 return SSL_TLSEXT_ERR_OK;
1040}
1041
1042/*
1043 * This function enables the handling of OCSP status extension on 'ctx' if a
1044 * file name 'cert_path' suffixed using ".ocsp" is present.
1045 * To enable OCSP status extension, the issuer's certificate is mandatory.
1046 * It should be present in the certificate's extra chain builded from file
1047 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1048 * named 'cert_path' suffixed using '.issuer'.
1049 *
1050 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1051 * response. If file is empty or content is not a valid OCSP response,
1052 * OCSP status extension is enabled but OCSP response is ignored (a warning
1053 * is displayed).
1054 *
1055 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001056 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001057 */
1058static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1059{
1060
1061 BIO *in = NULL;
1062 X509 *x, *xi = NULL, *issuer = NULL;
1063 STACK_OF(X509) *chain = NULL;
1064 OCSP_CERTID *cid = NULL;
1065 SSL *ssl;
1066 char ocsp_path[MAXPATHLEN+1];
1067 int i, ret = -1;
1068 struct stat st;
1069 struct certificate_ocsp *ocsp = NULL, *iocsp;
1070 char *warn = NULL;
1071 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001072 pem_password_cb *passwd_cb;
1073 void *passwd_cb_userdata;
1074 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001075
1076 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1077
1078 if (stat(ocsp_path, &st))
1079 return 1;
1080
1081 ssl = SSL_new(ctx);
1082 if (!ssl)
1083 goto out;
1084
1085 x = SSL_get_certificate(ssl);
1086 if (!x)
1087 goto out;
1088
1089 /* Try to lookup for issuer in certificate extra chain */
1090#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1091 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1092#else
1093 chain = ctx->extra_certs;
1094#endif
1095 for (i = 0; i < sk_X509_num(chain); i++) {
1096 issuer = sk_X509_value(chain, i);
1097 if (X509_check_issued(issuer, x) == X509_V_OK)
1098 break;
1099 else
1100 issuer = NULL;
1101 }
1102
1103 /* If not found try to load issuer from a suffixed file */
1104 if (!issuer) {
1105 char issuer_path[MAXPATHLEN+1];
1106
1107 in = BIO_new(BIO_s_file());
1108 if (!in)
1109 goto out;
1110
1111 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1112 if (BIO_read_filename(in, issuer_path) <= 0)
1113 goto out;
1114
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001115 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1116 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1117
1118 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001119 if (!xi)
1120 goto out;
1121
1122 if (X509_check_issued(xi, x) != X509_V_OK)
1123 goto out;
1124
1125 issuer = xi;
1126 }
1127
1128 cid = OCSP_cert_to_id(0, x, issuer);
1129 if (!cid)
1130 goto out;
1131
1132 i = i2d_OCSP_CERTID(cid, NULL);
1133 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1134 goto out;
1135
Vincent Bernat02779b62016-04-03 13:48:43 +02001136 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001137 if (!ocsp)
1138 goto out;
1139
1140 p = ocsp->key_data;
1141 i2d_OCSP_CERTID(cid, &p);
1142
1143 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1144 if (iocsp == ocsp)
1145 ocsp = NULL;
1146
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001147#ifndef SSL_CTX_get_tlsext_status_cb
1148# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1149 *cb = (void (*) (void))ctx->tlsext_status_cb;
1150#endif
1151 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1152
1153 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001154 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001155 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001156
1157 cb_arg->is_single = 1;
1158 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001159
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001160 pkey = X509_get_pubkey(x);
1161 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1162 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001163
1164 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1165 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1166 } else {
1167 /*
1168 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1169 * Update that cb_arg with the new cert's staple
1170 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001171 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001172 struct certificate_ocsp *tmp_ocsp;
1173 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001174 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001175 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001176
1177#ifdef SSL_CTX_get_tlsext_status_arg
1178 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1179#else
1180 cb_arg = ctx->tlsext_status_arg;
1181#endif
yanbzhube2774d2015-12-10 15:07:30 -05001182
1183 /*
1184 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1185 * the order of operations below matter, take care when changing it
1186 */
1187 tmp_ocsp = cb_arg->s_ocsp;
1188 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1189 cb_arg->s_ocsp = NULL;
1190 cb_arg->m_ocsp[index] = tmp_ocsp;
1191 cb_arg->is_single = 0;
1192 cb_arg->single_kt = 0;
1193
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001194 pkey = X509_get_pubkey(x);
1195 key_type = EVP_PKEY_base_id(pkey);
1196 EVP_PKEY_free(pkey);
1197
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001198 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001199 if (index >= 0 && !cb_arg->m_ocsp[index])
1200 cb_arg->m_ocsp[index] = iocsp;
1201
1202 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001203
1204 ret = 0;
1205
1206 warn = NULL;
1207 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1208 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001209 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001210 }
1211
1212out:
1213 if (ssl)
1214 SSL_free(ssl);
1215
1216 if (in)
1217 BIO_free(in);
1218
1219 if (xi)
1220 X509_free(xi);
1221
1222 if (cid)
1223 OCSP_CERTID_free(cid);
1224
1225 if (ocsp)
1226 free(ocsp);
1227
1228 if (warn)
1229 free(warn);
1230
1231
1232 return ret;
1233}
1234
1235#endif
1236
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001237#ifdef OPENSSL_IS_BORINGSSL
1238static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1239{
1240 char ocsp_path[MAXPATHLEN+1];
1241 struct stat st;
1242 int fd = -1, r = 0;
1243
1244 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1245 if (stat(ocsp_path, &st))
1246 return 0;
1247
1248 fd = open(ocsp_path, O_RDONLY);
1249 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001250 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001251 return -1;
1252 }
1253
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001254 trash.data = 0;
1255 while (trash.data < trash.size) {
1256 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001257 if (r < 0) {
1258 if (errno == EINTR)
1259 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001260 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001261 close(fd);
1262 return -1;
1263 }
1264 else if (r == 0) {
1265 break;
1266 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001267 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001268 }
1269 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001270 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1271 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001272}
1273#endif
1274
Daniel Jakots54ffb912015-11-06 20:02:41 +01001275#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001276
1277#define CT_EXTENSION_TYPE 18
1278
1279static int sctl_ex_index = -1;
1280
1281/*
1282 * Try to parse Signed Certificate Timestamp List structure. This function
1283 * makes only basic test if the data seems like SCTL. No signature validation
1284 * is performed.
1285 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001286static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001287{
1288 int ret = 1;
1289 int len, pos, sct_len;
1290 unsigned char *data;
1291
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001292 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001293 goto out;
1294
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001295 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001296 len = (data[0] << 8) | data[1];
1297
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001298 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001299 goto out;
1300
1301 data = data + 2;
1302 pos = 0;
1303 while (pos < len) {
1304 if (len - pos < 2)
1305 goto out;
1306
1307 sct_len = (data[pos] << 8) | data[pos + 1];
1308 if (pos + sct_len + 2 > len)
1309 goto out;
1310
1311 pos += sct_len + 2;
1312 }
1313
1314 ret = 0;
1315
1316out:
1317 return ret;
1318}
1319
Willy Tarreau83061a82018-07-13 11:56:34 +02001320static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1321 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001322{
1323 int fd = -1;
1324 int r = 0;
1325 int ret = 1;
1326
1327 *sctl = NULL;
1328
1329 fd = open(sctl_path, O_RDONLY);
1330 if (fd == -1)
1331 goto end;
1332
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001333 trash.data = 0;
1334 while (trash.data < trash.size) {
1335 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001336 if (r < 0) {
1337 if (errno == EINTR)
1338 continue;
1339
1340 goto end;
1341 }
1342 else if (r == 0) {
1343 break;
1344 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001345 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001346 }
1347
1348 ret = ssl_sock_parse_sctl(&trash);
1349 if (ret)
1350 goto end;
1351
Vincent Bernat02779b62016-04-03 13:48:43 +02001352 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001353 if (!chunk_dup(*sctl, &trash)) {
1354 free(*sctl);
1355 *sctl = NULL;
1356 goto end;
1357 }
1358
1359end:
1360 if (fd != -1)
1361 close(fd);
1362
1363 return ret;
1364}
1365
1366int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1367{
Willy Tarreau83061a82018-07-13 11:56:34 +02001368 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001369
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001370 *out = (unsigned char *) sctl->area;
1371 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001372
1373 return 1;
1374}
1375
1376int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1377{
1378 return 1;
1379}
1380
1381static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1382{
1383 char sctl_path[MAXPATHLEN+1];
1384 int ret = -1;
1385 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001386 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001387
1388 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1389
1390 if (stat(sctl_path, &st))
1391 return 1;
1392
1393 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1394 goto out;
1395
1396 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1397 free(sctl);
1398 goto out;
1399 }
1400
1401 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1402
1403 ret = 0;
1404
1405out:
1406 return ret;
1407}
1408
1409#endif
1410
Emeric Brune1f38db2012-09-03 20:36:47 +02001411void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1412{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001413 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001414 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001415 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001416
1417 if (where & SSL_CB_HANDSHAKE_START) {
1418 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001419 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001420 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001421 conn->err_code = CO_ER_SSL_RENEG;
1422 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001423 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001424
1425 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1426 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1427 /* Long certificate chains optimz
1428 If write and read bios are differents, we
1429 consider that the buffering was activated,
1430 so we rise the output buffer size from 4k
1431 to 16k */
1432 write_bio = SSL_get_wbio(ssl);
1433 if (write_bio != SSL_get_rbio(ssl)) {
1434 BIO_set_write_buffer_size(write_bio, 16384);
1435 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1436 }
1437 }
1438 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001439}
1440
Emeric Brune64aef12012-09-21 13:15:06 +02001441/* Callback is called for each certificate of the chain during a verify
1442 ok is set to 1 if preverify detect no error on current certificate.
1443 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001444int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001445{
1446 SSL *ssl;
1447 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001448 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001449
1450 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001451 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001452
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001453 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001454
Emeric Brun81c00f02012-09-21 14:31:21 +02001455 if (ok) /* no errors */
1456 return ok;
1457
1458 depth = X509_STORE_CTX_get_error_depth(x_store);
1459 err = X509_STORE_CTX_get_error(x_store);
1460
1461 /* check if CA error needs to be ignored */
1462 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001463 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1464 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1465 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001466 }
1467
Willy Tarreau07d94e42018-09-20 10:57:52 +02001468 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001469 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001470 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001471 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001472 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001473
Willy Tarreau20879a02012-12-03 16:32:10 +01001474 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001475 return 0;
1476 }
1477
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001478 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1479 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001480
Emeric Brun81c00f02012-09-21 14:31:21 +02001481 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001482 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001483 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001484 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001485 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001486 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001487
Willy Tarreau20879a02012-12-03 16:32:10 +01001488 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001489 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001490}
1491
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001492static inline
1493void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001494 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001495{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001496 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001497 unsigned char *msg;
1498 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001499 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001500
1501 /* This function is called for "from client" and "to server"
1502 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001503 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001504 */
1505
1506 /* "write_p" is set to 0 is the bytes are received messages,
1507 * otherwise it is set to 1.
1508 */
1509 if (write_p != 0)
1510 return;
1511
1512 /* content_type contains the type of message received or sent
1513 * according with the SSL/TLS protocol spec. This message is
1514 * encoded with one byte. The value 256 (two bytes) is used
1515 * for designing the SSL/TLS record layer. According with the
1516 * rfc6101, the expected message (other than 256) are:
1517 * - change_cipher_spec(20)
1518 * - alert(21)
1519 * - handshake(22)
1520 * - application_data(23)
1521 * - (255)
1522 * We are interessed by the handshake and specially the client
1523 * hello.
1524 */
1525 if (content_type != 22)
1526 return;
1527
1528 /* The message length is at least 4 bytes, containing the
1529 * message type and the message length.
1530 */
1531 if (len < 4)
1532 return;
1533
1534 /* First byte of the handshake message id the type of
1535 * message. The konwn types are:
1536 * - hello_request(0)
1537 * - client_hello(1)
1538 * - server_hello(2)
1539 * - certificate(11)
1540 * - server_key_exchange (12)
1541 * - certificate_request(13)
1542 * - server_hello_done(14)
1543 * We are interested by the client hello.
1544 */
1545 msg = (unsigned char *)buf;
1546 if (msg[0] != 1)
1547 return;
1548
1549 /* Next three bytes are the length of the message. The total length
1550 * must be this decoded length + 4. If the length given as argument
1551 * is not the same, we abort the protocol dissector.
1552 */
1553 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1554 if (len < rec_len + 4)
1555 return;
1556 msg += 4;
1557 end = msg + rec_len;
1558 if (end < msg)
1559 return;
1560
1561 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1562 * for minor, the random, composed by 4 bytes for the unix time and
1563 * 28 bytes for unix payload, and them 1 byte for the session id. So
1564 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1565 */
1566 msg += 1 + 1 + 4 + 28 + 1;
1567 if (msg > end)
1568 return;
1569
1570 /* Next two bytes are the ciphersuite length. */
1571 if (msg + 2 > end)
1572 return;
1573 rec_len = (msg[0] << 8) + msg[1];
1574 msg += 2;
1575 if (msg + rec_len > end || msg + rec_len < msg)
1576 return;
1577
Willy Tarreaubafbe012017-11-24 17:34:44 +01001578 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001579 if (!capture)
1580 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001581 /* Compute the xxh64 of the ciphersuite. */
1582 capture->xxh64 = XXH64(msg, rec_len, 0);
1583
1584 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001585 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1586 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001587 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001588
1589 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001590}
1591
Emeric Brun29f037d2014-04-25 19:05:36 +02001592/* Callback is called for ssl protocol analyse */
1593void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1594{
Emeric Brun29f037d2014-04-25 19:05:36 +02001595#ifdef TLS1_RT_HEARTBEAT
1596 /* test heartbeat received (write_p is set to 0
1597 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001598 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001599 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001600 const unsigned char *p = buf;
1601 unsigned int payload;
1602
Emeric Brun29f037d2014-04-25 19:05:36 +02001603 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001604
1605 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1606 if (*p != TLS1_HB_REQUEST)
1607 return;
1608
Willy Tarreauaeed6722014-04-25 23:59:58 +02001609 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001610 goto kill_it;
1611
1612 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001613 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001614 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001615 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001616 /* We have a clear heartbleed attack (CVE-2014-0160), the
1617 * advertised payload is larger than the advertised packet
1618 * length, so we have garbage in the buffer between the
1619 * payload and the end of the buffer (p+len). We can't know
1620 * if the SSL stack is patched, and we don't know if we can
1621 * safely wipe out the area between p+3+len and payload.
1622 * So instead, we prevent the response from being sent by
1623 * setting the max_send_fragment to 0 and we report an SSL
1624 * error, which will kill this connection. It will be reported
1625 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001626 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1627 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001628 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001629 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1630 return;
1631 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001632#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001633 if (global_ssl.capture_cipherlist > 0)
1634 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001635}
1636
Bernard Spil13c53f82018-02-15 13:34:58 +01001637#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001638static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1639 const unsigned char *in, unsigned int inlen,
1640 void *arg)
1641{
1642 struct server *srv = arg;
1643
1644 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1645 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1646 return SSL_TLSEXT_ERR_OK;
1647 return SSL_TLSEXT_ERR_NOACK;
1648}
1649#endif
1650
1651#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001652/* This callback is used so that the server advertises the list of
1653 * negociable protocols for NPN.
1654 */
1655static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1656 unsigned int *len, void *arg)
1657{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001658 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001659
1660 *data = (const unsigned char *)conf->npn_str;
1661 *len = conf->npn_len;
1662 return SSL_TLSEXT_ERR_OK;
1663}
1664#endif
1665
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001666#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001667/* This callback is used so that the server advertises the list of
1668 * negociable protocols for ALPN.
1669 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001670static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1671 unsigned char *outlen,
1672 const unsigned char *server,
1673 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001674{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001675 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001676
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001677 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1678 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1679 return SSL_TLSEXT_ERR_NOACK;
1680 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001681 return SSL_TLSEXT_ERR_OK;
1682}
1683#endif
1684
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001685#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001686#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001687
Christopher Faulet30548802015-06-11 13:39:32 +02001688/* Create a X509 certificate with the specified servername and serial. This
1689 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001690static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001691ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001692{
Christopher Faulet7969a332015-10-09 11:15:03 +02001693 X509 *cacert = bind_conf->ca_sign_cert;
1694 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001695 SSL_CTX *ssl_ctx = NULL;
1696 X509 *newcrt = NULL;
1697 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001698 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001699 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001700 X509_NAME *name;
1701 const EVP_MD *digest;
1702 X509V3_CTX ctx;
1703 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001704 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001705
Christopher Faulet48a83322017-07-28 16:56:09 +02001706 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001707#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1708 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1709#else
1710 tmp_ssl = SSL_new(bind_conf->default_ctx);
1711 if (tmp_ssl)
1712 pkey = SSL_get_privatekey(tmp_ssl);
1713#endif
1714 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001715 goto mkcert_error;
1716
1717 /* Create the certificate */
1718 if (!(newcrt = X509_new()))
1719 goto mkcert_error;
1720
1721 /* Set version number for the certificate (X509v3) and the serial
1722 * number */
1723 if (X509_set_version(newcrt, 2L) != 1)
1724 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001725 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001726
1727 /* Set duration for the certificate */
1728 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1729 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1730 goto mkcert_error;
1731
1732 /* set public key in the certificate */
1733 if (X509_set_pubkey(newcrt, pkey) != 1)
1734 goto mkcert_error;
1735
1736 /* Set issuer name from the CA */
1737 if (!(name = X509_get_subject_name(cacert)))
1738 goto mkcert_error;
1739 if (X509_set_issuer_name(newcrt, name) != 1)
1740 goto mkcert_error;
1741
1742 /* Set the subject name using the same, but the CN */
1743 name = X509_NAME_dup(name);
1744 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1745 (const unsigned char *)servername,
1746 -1, -1, 0) != 1) {
1747 X509_NAME_free(name);
1748 goto mkcert_error;
1749 }
1750 if (X509_set_subject_name(newcrt, name) != 1) {
1751 X509_NAME_free(name);
1752 goto mkcert_error;
1753 }
1754 X509_NAME_free(name);
1755
1756 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001757 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001758 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1759 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1760 X509_EXTENSION *ext;
1761
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001762 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001763 goto mkcert_error;
1764 if (!X509_add_ext(newcrt, ext, -1)) {
1765 X509_EXTENSION_free(ext);
1766 goto mkcert_error;
1767 }
1768 X509_EXTENSION_free(ext);
1769 }
1770
1771 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001772
1773 key_type = EVP_PKEY_base_id(capkey);
1774
1775 if (key_type == EVP_PKEY_DSA)
1776 digest = EVP_sha1();
1777 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001779 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001780 digest = EVP_sha256();
1781 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001782#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001783 int nid;
1784
1785 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1786 goto mkcert_error;
1787 if (!(digest = EVP_get_digestbynid(nid)))
1788 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001789#else
1790 goto mkcert_error;
1791#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001792 }
1793
Christopher Faulet31af49d2015-06-09 17:29:50 +02001794 if (!(X509_sign(newcrt, capkey, digest)))
1795 goto mkcert_error;
1796
1797 /* Create and set the new SSL_CTX */
1798 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1799 goto mkcert_error;
1800 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1801 goto mkcert_error;
1802 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1803 goto mkcert_error;
1804 if (!SSL_CTX_check_private_key(ssl_ctx))
1805 goto mkcert_error;
1806
1807 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001808
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001809#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001810 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001811#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001812#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1813 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001814 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001815 EC_KEY *ecc;
1816 int nid;
1817
1818 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1819 goto end;
1820 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1821 goto end;
1822 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1823 EC_KEY_free(ecc);
1824 }
1825#endif
1826 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001827 return ssl_ctx;
1828
1829 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001830 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001831 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001832 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1833 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001834 return NULL;
1835}
1836
Christopher Faulet7969a332015-10-09 11:15:03 +02001837SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001838ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001839{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001840 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001841
1842 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001843}
1844
Christopher Faulet30548802015-06-11 13:39:32 +02001845/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001846 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001847SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001848ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001849{
1850 struct lru64 *lru = NULL;
1851
1852 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001853 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001854 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001855 if (lru && lru->domain) {
1856 if (ssl)
1857 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001858 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001859 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001860 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001861 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001862 }
1863 return NULL;
1864}
1865
Emeric Brun821bb9b2017-06-15 16:37:39 +02001866/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1867 * function is not thread-safe, it should only be used to check if a certificate
1868 * exists in the lru cache (with no warranty it will not be removed by another
1869 * thread). It is kept for backward compatibility. */
1870SSL_CTX *
1871ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1872{
1873 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1874}
1875
Christopher Fauletd2cab922015-07-28 16:03:47 +02001876/* Set a certificate int the LRU cache used to store generated
1877 * certificate. Return 0 on success, otherwise -1 */
1878int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001879ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001880{
1881 struct lru64 *lru = NULL;
1882
1883 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001884 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001885 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001886 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001887 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001888 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001889 }
Christopher Faulet30548802015-06-11 13:39:32 +02001890 if (lru->domain && lru->data)
1891 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001892 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001893 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001894 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001895 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001896 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001897}
1898
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001899/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001900unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001901ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001902{
1903 return XXH32(data, len, ssl_ctx_lru_seed);
1904}
1905
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001906/* Generate a cert and immediately assign it to the SSL session so that the cert's
1907 * refcount is maintained regardless of the cert's presence in the LRU cache.
1908 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001909static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001910ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001911{
1912 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001913 SSL_CTX *ssl_ctx = NULL;
1914 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001915 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001916
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001917 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001918 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001919 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001920 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001921 if (lru && lru->domain)
1922 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001923 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001924 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001925 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001926 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001927 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001928 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001929 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001930 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001931 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001932 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001933 SSL_set_SSL_CTX(ssl, ssl_ctx);
1934 /* No LRU cache, this CTX will be released as soon as the session dies */
1935 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001936 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001937 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001938 return 0;
1939}
1940static int
1941ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1942{
1943 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001944 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001945
1946 conn_get_to_addr(conn);
1947 if (conn->flags & CO_FL_ADDR_TO_SET) {
1948 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001949 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001950 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001951 }
1952 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001953}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001954#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001955
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001956
1957#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1958#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1959#endif
1960
1961#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1962#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1963#define SSL_renegotiate_pending(arg) 0
1964#endif
1965#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1966#define SSL_OP_SINGLE_ECDH_USE 0
1967#endif
1968#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1969#define SSL_OP_NO_TICKET 0
1970#endif
1971#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1972#define SSL_OP_NO_COMPRESSION 0
1973#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001974#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1975#undef SSL_OP_NO_SSLv3
1976#define SSL_OP_NO_SSLv3 0
1977#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001978#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1979#define SSL_OP_NO_TLSv1_1 0
1980#endif
1981#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1982#define SSL_OP_NO_TLSv1_2 0
1983#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001984#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001985#define SSL_OP_NO_TLSv1_3 0
1986#endif
1987#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1988#define SSL_OP_SINGLE_DH_USE 0
1989#endif
1990#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1991#define SSL_OP_SINGLE_ECDH_USE 0
1992#endif
1993#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1994#define SSL_MODE_RELEASE_BUFFERS 0
1995#endif
1996#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1997#define SSL_MODE_SMALL_BUFFERS 0
1998#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02001999#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2000#define SSL_OP_PRIORITIZE_CHACHA 0
2001#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002002
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002003#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002004typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2005
2006static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002007{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002008#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002010 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2011#endif
2012}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002013static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2014 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2016}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002017static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002018#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2021#endif
2022}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002023static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002025 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002026 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2027#endif
2028}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002029/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002030static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2031/* Unusable in this context. */
2032static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2033static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2034static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2035static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2036static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002037#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002038typedef enum { SET_MIN, SET_MAX } set_context_func;
2039
2040static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2041 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002042 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2043}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002044static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2045 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2046 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2047}
2048static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2049 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002050 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2051}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002052static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2053 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2054 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2055}
2056static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2057 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002058 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2059}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2061 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2062 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2063}
2064static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2065 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002066 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2067}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002068static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2069 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2070 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2071}
2072static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002073#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002074 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002075 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2076#endif
2077}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002078static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2079#if SSL_OP_NO_TLSv1_3
2080 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2081 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002082#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002084#endif
2085static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2086static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002087
2088static struct {
2089 int option;
2090 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002091 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2092 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002093 const char *name;
2094} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002095 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2096 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2097 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2098 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2099 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2100 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002101};
2102
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002103static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2104{
2105 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2106 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2107 SSL_set_SSL_CTX(ssl, ctx);
2108}
2109
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002110#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002111
2112static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2113{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002114 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002115 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002117 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2118 return SSL_TLSEXT_ERR_OK;
2119 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002120}
2121
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002122#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002123static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2124{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002125 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002126#else
2127static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2128{
2129#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002130 struct connection *conn;
2131 struct bind_conf *s;
2132 const uint8_t *extension_data;
2133 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002134 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002135
2136 char *wildp = NULL;
2137 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002138 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002139 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002140 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002141 int i;
2142
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002143 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002144 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002145
Olivier Houchard9679ac92017-10-27 14:58:08 +02002146 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002147 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002148#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002149 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2150 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002151#else
2152 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2153#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002154 /*
2155 * The server_name extension was given too much extensibility when it
2156 * was written, so parsing the normal case is a bit complex.
2157 */
2158 size_t len;
2159 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002160 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002161 /* Extract the length of the supplied list of names. */
2162 len = (*extension_data++) << 8;
2163 len |= *extension_data++;
2164 if (len + 2 != extension_len)
2165 goto abort;
2166 /*
2167 * The list in practice only has a single element, so we only consider
2168 * the first one.
2169 */
2170 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2171 goto abort;
2172 extension_len = len - 1;
2173 /* Now we can finally pull out the byte array with the actual hostname. */
2174 if (extension_len <= 2)
2175 goto abort;
2176 len = (*extension_data++) << 8;
2177 len |= *extension_data++;
2178 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2179 || memchr(extension_data, 0, len) != NULL)
2180 goto abort;
2181 servername = extension_data;
2182 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002183 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002184#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2185 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002186 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002187 }
2188#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002189 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002190 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002191 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002192 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002193 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002194 goto abort;
2195 }
2196
2197 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002198#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002200#else
2201 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2202#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002203 uint8_t sign;
2204 size_t len;
2205 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002206 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002207 len = (*extension_data++) << 8;
2208 len |= *extension_data++;
2209 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002210 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002211 if (len % 2 != 0)
2212 goto abort;
2213 for (; len > 0; len -= 2) {
2214 extension_data++; /* hash */
2215 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002216 switch (sign) {
2217 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002218 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002219 break;
2220 case TLSEXT_signature_ecdsa:
2221 has_ecdsa_sig = 1;
2222 break;
2223 default:
2224 continue;
2225 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002226 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002227 break;
2228 }
2229 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002230 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002231 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002232 }
2233 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002234 const SSL_CIPHER *cipher;
2235 size_t len;
2236 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002237 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002238#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002239 len = ctx->cipher_suites_len;
2240 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002241#else
2242 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2243#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 if (len % 2 != 0)
2245 goto abort;
2246 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002247#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002248 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002249 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002250#else
2251 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2252#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002253 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002254 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002255 break;
2256 }
2257 }
2258 }
2259
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002260 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002261 trash.area[i] = tolower(servername[i]);
2262 if (!wildp && (trash.area[i] == '.'))
2263 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002264 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002265 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002266
2267 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002268 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002269
2270 /* lookup a not neg filter */
2271 for (n = node; n; n = ebmb_next_dup(n)) {
2272 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002273 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002274 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002275 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 break;
2278 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002279 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002280 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002282 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 if (!node_anonymous)
2284 node_anonymous = n;
2285 break;
2286 }
2287 }
2288 }
2289 if (wildp) {
2290 /* lookup in wildcards names */
2291 node = ebst_lookup(&s->sni_w_ctx, wildp);
2292 for (n = node; n; n = ebmb_next_dup(n)) {
2293 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002294 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002295 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002296 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 break;
2299 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002300 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002301 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002302 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002303 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 if (!node_anonymous)
2305 node_anonymous = n;
2306 break;
2307 }
2308 }
2309 }
2310 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002311 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002312 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2313 : ((has_rsa_sig && node_rsa) ? node_rsa
2314 : (node_anonymous ? node_anonymous
2315 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2316 : node_rsa /* no rsa signature case (far far away) */
2317 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002318 if (node) {
2319 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002320 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002321 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002322 if (conf) {
2323 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2324 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2325 if (conf->early_data)
2326 allow_early = 1;
2327 }
2328 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002329 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002330#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002331 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002332 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002333 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002334 }
2335#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002336 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002337 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002338 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002339 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002340allow_early:
2341#ifdef OPENSSL_IS_BORINGSSL
2342 if (allow_early)
2343 SSL_set_early_data_enabled(ssl, 1);
2344#else
2345 if (!allow_early)
2346 SSL_set_max_early_data(ssl, 0);
2347#endif
2348 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002349 abort:
2350 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2351 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002352#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002353 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002354#else
2355 *al = SSL_AD_UNRECOGNIZED_NAME;
2356 return 0;
2357#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358}
2359
2360#else /* OPENSSL_IS_BORINGSSL */
2361
Emeric Brunfc0421f2012-09-07 17:30:07 +02002362/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2363 * warning when no match is found, which implies the default (first) cert
2364 * will keep being used.
2365 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002366static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002367{
2368 const char *servername;
2369 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002370 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002371 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372 int i;
2373 (void)al; /* shut gcc stupid warning */
2374
2375 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002376 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002377#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002378 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2379 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002380#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002381 if (s->strict_sni)
2382 return SSL_TLSEXT_ERR_ALERT_FATAL;
2383 ssl_sock_switchctx_set(ssl, s->default_ctx);
2384 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002385 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002386
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002387 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002388 if (!servername[i])
2389 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002390 trash.area[i] = tolower(servername[i]);
2391 if (!wildp && (trash.area[i] == '.'))
2392 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002393 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002394 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002395
2396 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002397 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002398
2399 /* lookup a not neg filter */
2400 for (n = node; n; n = ebmb_next_dup(n)) {
2401 if (!container_of(n, struct sni_ctx, name)->neg) {
2402 node = n;
2403 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002404 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002405 }
2406 if (!node && wildp) {
2407 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002408 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002409 }
2410 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002411#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002412 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2413 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002414 return SSL_TLSEXT_ERR_OK;
2415 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002416#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002417 if (s->strict_sni)
2418 return SSL_TLSEXT_ERR_ALERT_FATAL;
2419 ssl_sock_switchctx_set(ssl, s->default_ctx);
2420 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002421 }
2422
2423 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002424 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002425 return SSL_TLSEXT_ERR_OK;
2426}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002427#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002428#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2429
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002430#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002431
2432static DH * ssl_get_dh_1024(void)
2433{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002434 static unsigned char dh1024_p[]={
2435 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2436 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2437 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2438 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2439 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2440 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2441 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2442 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2443 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2444 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2445 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2446 };
2447 static unsigned char dh1024_g[]={
2448 0x02,
2449 };
2450
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002451 BIGNUM *p;
2452 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002453 DH *dh = DH_new();
2454 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002455 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2456 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002457
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002458 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002459 DH_free(dh);
2460 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002461 } else {
2462 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002463 }
2464 }
2465 return dh;
2466}
2467
2468static DH *ssl_get_dh_2048(void)
2469{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002470 static unsigned char dh2048_p[]={
2471 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2472 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2473 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2474 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2475 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2476 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2477 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2478 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2479 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2480 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2481 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2482 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2483 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2484 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2485 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2486 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2487 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2488 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2489 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2490 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2491 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2492 0xB7,0x1F,0x77,0xF3,
2493 };
2494 static unsigned char dh2048_g[]={
2495 0x02,
2496 };
2497
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002498 BIGNUM *p;
2499 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002500 DH *dh = DH_new();
2501 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002502 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2503 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002504
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002505 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002506 DH_free(dh);
2507 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002508 } else {
2509 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002510 }
2511 }
2512 return dh;
2513}
2514
2515static DH *ssl_get_dh_4096(void)
2516{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002517 static unsigned char dh4096_p[]={
2518 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2519 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2520 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2521 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2522 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2523 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2524 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2525 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2526 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2527 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2528 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2529 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2530 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2531 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2532 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2533 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2534 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2535 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2536 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2537 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2538 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2539 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2540 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2541 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2542 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2543 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2544 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2545 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2546 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2547 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2548 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2549 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2550 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2551 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2552 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2553 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2554 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2555 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2556 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2557 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2558 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2559 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2560 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002561 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002562 static unsigned char dh4096_g[]={
2563 0x02,
2564 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002565
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002566 BIGNUM *p;
2567 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002568 DH *dh = DH_new();
2569 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002570 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2571 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002572
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002573 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002574 DH_free(dh);
2575 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002576 } else {
2577 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 }
2579 }
2580 return dh;
2581}
2582
2583/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002584 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002585static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2586{
2587 DH *dh = NULL;
2588 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002589 int type;
2590
2591 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002592
2593 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2594 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2595 */
2596 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2597 keylen = EVP_PKEY_bits(pkey);
2598 }
2599
Willy Tarreauef934602016-12-22 23:12:01 +01002600 if (keylen > global_ssl.default_dh_param) {
2601 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002602 }
2603
Remi Gacogned3a341a2015-05-29 16:26:17 +02002604 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002605 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002606 }
2607 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002608 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002609 }
2610 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002611 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002612 }
2613
2614 return dh;
2615}
2616
Remi Gacogne47783ef2015-05-29 15:53:22 +02002617static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002618{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002619 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002620 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002621
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002622 if (in == NULL)
2623 goto end;
2624
Remi Gacogne47783ef2015-05-29 15:53:22 +02002625 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002626 goto end;
2627
Remi Gacogne47783ef2015-05-29 15:53:22 +02002628 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2629
2630end:
2631 if (in)
2632 BIO_free(in);
2633
Emeric Brune1b4ed42018-08-16 15:14:12 +02002634 ERR_clear_error();
2635
Remi Gacogne47783ef2015-05-29 15:53:22 +02002636 return dh;
2637}
2638
2639int ssl_sock_load_global_dh_param_from_file(const char *filename)
2640{
2641 global_dh = ssl_sock_get_dh_from_file(filename);
2642
2643 if (global_dh) {
2644 return 0;
2645 }
2646
2647 return -1;
2648}
2649
2650/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002651 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002652int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2653{
2654 int ret = -1;
2655 DH *dh = ssl_sock_get_dh_from_file(file);
2656
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002657 if (dh) {
2658 ret = 1;
2659 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002660
2661 if (ssl_dh_ptr_index >= 0) {
2662 /* store a pointer to the DH params to avoid complaining about
2663 ssl-default-dh-param not being set for this SSL_CTX */
2664 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2665 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002666 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002667 else if (global_dh) {
2668 SSL_CTX_set_tmp_dh(ctx, global_dh);
2669 ret = 0; /* DH params not found */
2670 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002671 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002672 /* Clear openssl global errors stack */
2673 ERR_clear_error();
2674
Willy Tarreauef934602016-12-22 23:12:01 +01002675 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002676 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002677 if (local_dh_1024 == NULL)
2678 local_dh_1024 = ssl_get_dh_1024();
2679
Remi Gacogne8de54152014-07-15 11:36:40 +02002680 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002681 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002682
Remi Gacogne8de54152014-07-15 11:36:40 +02002683 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002684 }
2685 else {
2686 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2687 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002688
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002689 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002690 }
Emeric Brun644cde02012-12-14 11:21:13 +01002691
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002692end:
2693 if (dh)
2694 DH_free(dh);
2695
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002696 return ret;
2697}
2698#endif
2699
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002700static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002701 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002702{
2703 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002704 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002705 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002706
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002707 if (*name == '!') {
2708 neg = 1;
2709 name++;
2710 }
2711 if (*name == '*') {
2712 wild = 1;
2713 name++;
2714 }
2715 /* !* filter is a nop */
2716 if (neg && wild)
2717 return order;
2718 if (*name) {
2719 int j, len;
2720 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002721 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002722 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002723 if (j >= trash.size)
2724 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002725 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002726
2727 /* Check for duplicates. */
2728 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002729 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002730 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002731 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002732 for (; node; node = ebmb_next_dup(node)) {
2733 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002734 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002735 return order;
2736 }
2737
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002738 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002739 if (!sc)
2740 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002741 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002742 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002743 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002744 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002745 sc->order = order++;
2746 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002747 if (kinfo.sig != TLSEXT_signature_anonymous)
2748 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002749 if (wild)
2750 ebst_insert(&s->sni_w_ctx, &sc->name);
2751 else
2752 ebst_insert(&s->sni_ctx, &sc->name);
2753 }
2754 return order;
2755}
2756
yanbzhu488a4d22015-12-01 15:16:07 -05002757
2758/* The following code is used for loading multiple crt files into
2759 * SSL_CTX's based on CN/SAN
2760 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002761#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002762/* This is used to preload the certifcate, private key
2763 * and Cert Chain of a file passed in via the crt
2764 * argument
2765 *
2766 * This way, we do not have to read the file multiple times
2767 */
2768struct cert_key_and_chain {
2769 X509 *cert;
2770 EVP_PKEY *key;
2771 unsigned int num_chain_certs;
2772 /* This is an array of X509 pointers */
2773 X509 **chain_certs;
2774};
2775
yanbzhu08ce6ab2015-12-02 13:01:29 -05002776#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2777
2778struct key_combo_ctx {
2779 SSL_CTX *ctx;
2780 int order;
2781};
2782
2783/* Map used for processing multiple keypairs for a single purpose
2784 *
2785 * This maps CN/SNI name to certificate type
2786 */
2787struct sni_keytype {
2788 int keytypes; /* BITMASK for keytypes */
2789 struct ebmb_node name; /* node holding the servername value */
2790};
2791
2792
yanbzhu488a4d22015-12-01 15:16:07 -05002793/* Frees the contents of a cert_key_and_chain
2794 */
2795static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2796{
2797 int i;
2798
2799 if (!ckch)
2800 return;
2801
2802 /* Free the certificate and set pointer to NULL */
2803 if (ckch->cert)
2804 X509_free(ckch->cert);
2805 ckch->cert = NULL;
2806
2807 /* Free the key and set pointer to NULL */
2808 if (ckch->key)
2809 EVP_PKEY_free(ckch->key);
2810 ckch->key = NULL;
2811
2812 /* Free each certificate in the chain */
2813 for (i = 0; i < ckch->num_chain_certs; i++) {
2814 if (ckch->chain_certs[i])
2815 X509_free(ckch->chain_certs[i]);
2816 }
2817
2818 /* Free the chain obj itself and set to NULL */
2819 if (ckch->num_chain_certs > 0) {
2820 free(ckch->chain_certs);
2821 ckch->num_chain_certs = 0;
2822 ckch->chain_certs = NULL;
2823 }
2824
2825}
2826
2827/* checks if a key and cert exists in the ckch
2828 */
2829static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2830{
2831 return (ckch->cert != NULL && ckch->key != NULL);
2832}
2833
2834
2835/* Loads the contents of a crt file (path) into a cert_key_and_chain
2836 * This allows us to carry the contents of the file without having to
2837 * read the file multiple times.
2838 *
2839 * returns:
2840 * 0 on Success
2841 * 1 on SSL Failure
2842 * 2 on file not found
2843 */
2844static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2845{
2846
2847 BIO *in;
2848 X509 *ca = NULL;
2849 int ret = 1;
2850
2851 ssl_sock_free_cert_key_and_chain_contents(ckch);
2852
2853 in = BIO_new(BIO_s_file());
2854 if (in == NULL)
2855 goto end;
2856
2857 if (BIO_read_filename(in, path) <= 0)
2858 goto end;
2859
yanbzhu488a4d22015-12-01 15:16:07 -05002860 /* Read Private Key */
2861 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2862 if (ckch->key == NULL) {
2863 memprintf(err, "%sunable to load private key from file '%s'.\n",
2864 err && *err ? *err : "", path);
2865 goto end;
2866 }
2867
Willy Tarreaubb137a82016-04-06 19:02:38 +02002868 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002869 if (BIO_reset(in) == -1) {
2870 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2871 err && *err ? *err : "", path);
2872 goto end;
2873 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002874
2875 /* Read Certificate */
2876 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2877 if (ckch->cert == NULL) {
2878 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2879 err && *err ? *err : "", path);
2880 goto end;
2881 }
2882
yanbzhu488a4d22015-12-01 15:16:07 -05002883 /* Read Certificate Chain */
2884 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2885 /* Grow the chain certs */
2886 ckch->num_chain_certs++;
2887 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2888
2889 /* use - 1 here since we just incremented it above */
2890 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2891 }
2892 ret = ERR_get_error();
2893 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2894 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2895 err && *err ? *err : "", path);
2896 ret = 1;
2897 goto end;
2898 }
2899
2900 ret = 0;
2901
2902end:
2903
2904 ERR_clear_error();
2905 if (in)
2906 BIO_free(in);
2907
2908 /* Something went wrong in one of the reads */
2909 if (ret != 0)
2910 ssl_sock_free_cert_key_and_chain_contents(ckch);
2911
2912 return ret;
2913}
2914
2915/* Loads the info in ckch into ctx
2916 * Currently, this does not process any information about ocsp, dhparams or
2917 * sctl
2918 * Returns
2919 * 0 on success
2920 * 1 on failure
2921 */
2922static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2923{
2924 int i = 0;
2925
2926 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2927 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2928 err && *err ? *err : "", path);
2929 return 1;
2930 }
2931
2932 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2933 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2934 err && *err ? *err : "", path);
2935 return 1;
2936 }
2937
yanbzhu488a4d22015-12-01 15:16:07 -05002938 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2939 for (i = 0; i < ckch->num_chain_certs; i++) {
2940 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002941 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2942 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002943 return 1;
2944 }
2945 }
2946
2947 if (SSL_CTX_check_private_key(ctx) <= 0) {
2948 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2949 err && *err ? *err : "", path);
2950 return 1;
2951 }
2952
2953 return 0;
2954}
2955
yanbzhu08ce6ab2015-12-02 13:01:29 -05002956
2957static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2958{
2959 struct sni_keytype *s_kt = NULL;
2960 struct ebmb_node *node;
2961 int i;
2962
2963 for (i = 0; i < trash.size; i++) {
2964 if (!str[i])
2965 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002966 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002967 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002968 trash.area[i] = 0;
2969 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002970 if (!node) {
2971 /* CN not found in tree */
2972 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2973 /* Using memcpy here instead of strncpy.
2974 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2975 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2976 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002977 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002978 s_kt->keytypes = 0;
2979 ebst_insert(sni_keytypes, &s_kt->name);
2980 } else {
2981 /* CN found in tree */
2982 s_kt = container_of(node, struct sni_keytype, name);
2983 }
2984
2985 /* Mark that this CN has the keytype of key_index via keytypes mask */
2986 s_kt->keytypes |= 1<<key_index;
2987
2988}
2989
2990
2991/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2992 * If any are found, group these files into a set of SSL_CTX*
2993 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2994 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08002995 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05002996 *
2997 * Returns
2998 * 0 on success
2999 * 1 on failure
3000 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003001static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3002 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003003{
3004 char fp[MAXPATHLEN+1] = {0};
3005 int n = 0;
3006 int i = 0;
3007 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3008 struct eb_root sni_keytypes_map = { {0} };
3009 struct ebmb_node *node;
3010 struct ebmb_node *next;
3011 /* Array of SSL_CTX pointers corresponding to each possible combo
3012 * of keytypes
3013 */
3014 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3015 int rv = 0;
3016 X509_NAME *xname = NULL;
3017 char *str = NULL;
3018#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3019 STACK_OF(GENERAL_NAME) *names = NULL;
3020#endif
3021
3022 /* Load all possible certs and keys */
3023 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3024 struct stat buf;
3025
3026 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3027 if (stat(fp, &buf) == 0) {
3028 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3029 rv = 1;
3030 goto end;
3031 }
3032 }
3033 }
3034
3035 /* Process each ckch and update keytypes for each CN/SAN
3036 * for example, if CN/SAN www.a.com is associated with
3037 * certs with keytype 0 and 2, then at the end of the loop,
3038 * www.a.com will have:
3039 * keyindex = 0 | 1 | 4 = 5
3040 */
3041 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3042
3043 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3044 continue;
3045
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003046 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003047 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003048 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3049 } else {
3050 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3051 * so the line that contains logic is marked via comments
3052 */
3053 xname = X509_get_subject_name(certs_and_keys[n].cert);
3054 i = -1;
3055 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3056 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003057 ASN1_STRING *value;
3058 value = X509_NAME_ENTRY_get_data(entry);
3059 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003060 /* Important line is here */
3061 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003062
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003063 OPENSSL_free(str);
3064 str = NULL;
3065 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003066 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003067
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003068 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003069#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003070 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3071 if (names) {
3072 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3073 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003074
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003075 if (name->type == GEN_DNS) {
3076 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3077 /* Important line is here */
3078 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003079
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003080 OPENSSL_free(str);
3081 str = NULL;
3082 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003083 }
3084 }
3085 }
3086 }
3087#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3088 }
3089
3090 /* If no files found, return error */
3091 if (eb_is_empty(&sni_keytypes_map)) {
3092 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3093 err && *err ? *err : "", path);
3094 rv = 1;
3095 goto end;
3096 }
3097
3098 /* We now have a map of CN/SAN to keytypes that are loaded in
3099 * Iterate through the map to create the SSL_CTX's (if needed)
3100 * and add each CTX to the SNI tree
3101 *
3102 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003103 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003104 * combination is denoted by the key in the map. Each key
3105 * has a value between 1 and 2^n - 1. Conveniently, the array
3106 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3107 * entry in the array to correspond to the unique combo (key)
3108 * associated with i. This unique key combo (i) will be associated
3109 * with combos[i-1]
3110 */
3111
3112 node = ebmb_first(&sni_keytypes_map);
3113 while (node) {
3114 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003115 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003116 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003117
3118 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3119 i = container_of(node, struct sni_keytype, name)->keytypes;
3120 cur_ctx = key_combos[i-1].ctx;
3121
3122 if (cur_ctx == NULL) {
3123 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003124 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003125 if (cur_ctx == NULL) {
3126 memprintf(err, "%sunable to allocate SSL context.\n",
3127 err && *err ? *err : "");
3128 rv = 1;
3129 goto end;
3130 }
3131
yanbzhube2774d2015-12-10 15:07:30 -05003132 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003133 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3134 if (i & (1<<n)) {
3135 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003136 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3137 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003138 SSL_CTX_free(cur_ctx);
3139 rv = 1;
3140 goto end;
3141 }
yanbzhube2774d2015-12-10 15:07:30 -05003142
3143#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3144 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003145 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003146 if (err)
3147 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003148 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003149 SSL_CTX_free(cur_ctx);
3150 rv = 1;
3151 goto end;
3152 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003153#elif (defined OPENSSL_IS_BORINGSSL)
3154 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003155#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003156 }
3157 }
3158
3159 /* Load DH params into the ctx to support DHE keys */
3160#ifndef OPENSSL_NO_DH
3161 if (ssl_dh_ptr_index >= 0)
3162 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3163
3164 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3165 if (rv < 0) {
3166 if (err)
3167 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3168 *err ? *err : "", path);
3169 rv = 1;
3170 goto end;
3171 }
3172#endif
3173
3174 /* Update key_combos */
3175 key_combos[i-1].ctx = cur_ctx;
3176 }
3177
3178 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003179 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003180 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003181 node = ebmb_next(node);
3182 }
3183
3184
3185 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3186 if (!bind_conf->default_ctx) {
3187 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3188 if (key_combos[i].ctx) {
3189 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003190 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003191 break;
3192 }
3193 }
3194 }
3195
3196end:
3197
3198 if (names)
3199 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3200
3201 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3202 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3203
3204 node = ebmb_first(&sni_keytypes_map);
3205 while (node) {
3206 next = ebmb_next(node);
3207 ebmb_delete(node);
3208 node = next;
3209 }
3210
3211 return rv;
3212}
3213#else
3214/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003215static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3216 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003217{
3218 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3219 err && *err ? *err : "", path, strerror(errno));
3220 return 1;
3221}
3222
yanbzhu488a4d22015-12-01 15:16:07 -05003223#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3224
Emeric Brunfc0421f2012-09-07 17:30:07 +02003225/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3226 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3227 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003228static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3229 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003230{
3231 BIO *in;
3232 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003233 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003234 int ret = -1;
3235 int order = 0;
3236 X509_NAME *xname;
3237 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003238 pem_password_cb *passwd_cb;
3239 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003240 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003241 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003242
Emeric Brunfc0421f2012-09-07 17:30:07 +02003243#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3244 STACK_OF(GENERAL_NAME) *names;
3245#endif
3246
3247 in = BIO_new(BIO_s_file());
3248 if (in == NULL)
3249 goto end;
3250
3251 if (BIO_read_filename(in, file) <= 0)
3252 goto end;
3253
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003254
3255 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3256 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3257
3258 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003259 if (x == NULL)
3260 goto end;
3261
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003262 pkey = X509_get_pubkey(x);
3263 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003264 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003265 switch(EVP_PKEY_base_id(pkey)) {
3266 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003267 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003268 break;
3269 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003270 kinfo.sig = TLSEXT_signature_ecdsa;
3271 break;
3272 case EVP_PKEY_DSA:
3273 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003274 break;
3275 }
3276 EVP_PKEY_free(pkey);
3277 }
3278
Emeric Brun50bcecc2013-04-22 13:05:23 +02003279 if (fcount) {
3280 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003281 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003282 }
3283 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003284#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003285 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3286 if (names) {
3287 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3288 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3289 if (name->type == GEN_DNS) {
3290 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003291 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003292 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003293 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294 }
3295 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003296 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003297 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003298#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003299 xname = X509_get_subject_name(x);
3300 i = -1;
3301 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3302 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003303 ASN1_STRING *value;
3304
3305 value = X509_NAME_ENTRY_get_data(entry);
3306 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003307 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003308 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003309 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003310 }
3311 }
3312
3313 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3314 if (!SSL_CTX_use_certificate(ctx, x))
3315 goto end;
3316
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003317#ifdef SSL_CTX_clear_extra_chain_certs
3318 SSL_CTX_clear_extra_chain_certs(ctx);
3319#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003320 if (ctx->extra_certs != NULL) {
3321 sk_X509_pop_free(ctx->extra_certs, X509_free);
3322 ctx->extra_certs = NULL;
3323 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003324#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003325
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003326 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003327 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3328 X509_free(ca);
3329 goto end;
3330 }
3331 }
3332
3333 err = ERR_get_error();
3334 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3335 /* we successfully reached the last cert in the file */
3336 ret = 1;
3337 }
3338 ERR_clear_error();
3339
3340end:
3341 if (x)
3342 X509_free(x);
3343
3344 if (in)
3345 BIO_free(in);
3346
3347 return ret;
3348}
3349
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003350static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3351 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003352{
3353 int ret;
3354 SSL_CTX *ctx;
3355
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003356 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003357 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003358 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3359 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003360 return 1;
3361 }
3362
3363 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003364 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3365 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003366 SSL_CTX_free(ctx);
3367 return 1;
3368 }
3369
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003370 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003371 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003372 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3373 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003374 if (ret < 0) /* serious error, must do that ourselves */
3375 SSL_CTX_free(ctx);
3376 return 1;
3377 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003378
3379 if (SSL_CTX_check_private_key(ctx) <= 0) {
3380 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3381 err && *err ? *err : "", path);
3382 return 1;
3383 }
3384
Emeric Brunfc0421f2012-09-07 17:30:07 +02003385 /* we must not free the SSL_CTX anymore below, since it's already in
3386 * the tree, so it will be discovered and cleaned in time.
3387 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003388#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003389 /* store a NULL pointer to indicate we have not yet loaded
3390 a custom DH param file */
3391 if (ssl_dh_ptr_index >= 0) {
3392 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3393 }
3394
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003395 ret = ssl_sock_load_dh_params(ctx, path);
3396 if (ret < 0) {
3397 if (err)
3398 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3399 *err ? *err : "", path);
3400 return 1;
3401 }
3402#endif
3403
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003404#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003405 ret = ssl_sock_load_ocsp(ctx, path);
3406 if (ret < 0) {
3407 if (err)
3408 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3409 *err ? *err : "", path);
3410 return 1;
3411 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003412#elif (defined OPENSSL_IS_BORINGSSL)
3413 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003414#endif
3415
Daniel Jakots54ffb912015-11-06 20:02:41 +01003416#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003417 if (sctl_ex_index >= 0) {
3418 ret = ssl_sock_load_sctl(ctx, path);
3419 if (ret < 0) {
3420 if (err)
3421 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3422 *err ? *err : "", path);
3423 return 1;
3424 }
3425 }
3426#endif
3427
Emeric Brunfc0421f2012-09-07 17:30:07 +02003428#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003429 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003430 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3431 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003432 return 1;
3433 }
3434#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003435 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003436 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003437 bind_conf->default_ssl_conf = ssl_conf;
3438 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003439
3440 return 0;
3441}
3442
Willy Tarreau03209342016-12-22 17:08:28 +01003443int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003444{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003445 struct dirent **de_list;
3446 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003447 DIR *dir;
3448 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003449 char *end;
3450 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003451 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003452#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3453 int is_bundle;
3454 int j;
3455#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003456
yanbzhu08ce6ab2015-12-02 13:01:29 -05003457 if (stat(path, &buf) == 0) {
3458 dir = opendir(path);
3459 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003460 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003461
yanbzhu08ce6ab2015-12-02 13:01:29 -05003462 /* strip trailing slashes, including first one */
3463 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3464 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003465
yanbzhu08ce6ab2015-12-02 13:01:29 -05003466 n = scandir(path, &de_list, 0, alphasort);
3467 if (n < 0) {
3468 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3469 err && *err ? *err : "", path, strerror(errno));
3470 cfgerr++;
3471 }
3472 else {
3473 for (i = 0; i < n; i++) {
3474 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003475
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476 end = strrchr(de->d_name, '.');
3477 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3478 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003479
yanbzhu08ce6ab2015-12-02 13:01:29 -05003480 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3481 if (stat(fp, &buf) != 0) {
3482 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3483 err && *err ? *err : "", fp, strerror(errno));
3484 cfgerr++;
3485 goto ignore_entry;
3486 }
3487 if (!S_ISREG(buf.st_mode))
3488 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003489
3490#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3491 is_bundle = 0;
3492 /* Check if current entry in directory is part of a multi-cert bundle */
3493
3494 if (end) {
3495 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3496 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3497 is_bundle = 1;
3498 break;
3499 }
3500 }
3501
3502 if (is_bundle) {
3503 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3504 int dp_len;
3505
3506 dp_len = end - de->d_name;
3507 snprintf(dp, dp_len + 1, "%s", de->d_name);
3508
3509 /* increment i and free de until we get to a non-bundle cert
3510 * Note here that we look at de_list[i + 1] before freeing de
3511 * this is important since ignore_entry will free de
3512 */
3513 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3514 free(de);
3515 i++;
3516 de = de_list[i];
3517 }
3518
3519 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003520 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003521
3522 /* Successfully processed the bundle */
3523 goto ignore_entry;
3524 }
3525 }
3526
3527#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003528 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003529ignore_entry:
3530 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003531 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003532 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003533 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003534 closedir(dir);
3535 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003536 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003537
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003539
Emeric Brunfc0421f2012-09-07 17:30:07 +02003540 return cfgerr;
3541}
3542
Thierry Fournier383085f2013-01-24 14:15:43 +01003543/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3544 * done once. Zero is returned if the operation fails. No error is returned
3545 * if the random is said as not implemented, because we expect that openssl
3546 * will use another method once needed.
3547 */
3548static int ssl_initialize_random()
3549{
3550 unsigned char random;
3551 static int random_initialized = 0;
3552
3553 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3554 random_initialized = 1;
3555
3556 return random_initialized;
3557}
3558
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003559/* release ssl bind conf */
3560void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003561{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003562 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003563#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003564 free(conf->npn_str);
3565 conf->npn_str = NULL;
3566#endif
3567#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3568 free(conf->alpn_str);
3569 conf->alpn_str = NULL;
3570#endif
3571 free(conf->ca_file);
3572 conf->ca_file = NULL;
3573 free(conf->crl_file);
3574 conf->crl_file = NULL;
3575 free(conf->ciphers);
3576 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003577#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3578 free(conf->ciphersuites);
3579 conf->ciphersuites = NULL;
3580#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003581 free(conf->curves);
3582 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003583 free(conf->ecdhe);
3584 conf->ecdhe = NULL;
3585 }
3586}
3587
3588int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3589{
3590 char thisline[CRT_LINESIZE];
3591 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003592 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003593 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003594 int linenum = 0;
3595 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003596
Willy Tarreauad1731d2013-04-02 17:35:58 +02003597 if ((f = fopen(file, "r")) == NULL) {
3598 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003599 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003600 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003601
3602 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003603 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003605 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003607 char *crt_path;
3608 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003609
3610 linenum++;
3611 end = line + strlen(line);
3612 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3613 /* Check if we reached the limit and the last char is not \n.
3614 * Watch out for the last line without the terminating '\n'!
3615 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003616 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3617 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003618 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003619 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003620 }
3621
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003622 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003623 newarg = 1;
3624 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003625 if (*line == '#' || *line == '\n' || *line == '\r') {
3626 /* end of string, end of loop */
3627 *line = 0;
3628 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003629 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003630 newarg = 1;
3631 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003632 } else if (*line == '[') {
3633 if (ssl_b) {
3634 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3635 cfgerr = 1;
3636 break;
3637 }
3638 if (!arg) {
3639 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3640 cfgerr = 1;
3641 break;
3642 }
3643 ssl_b = arg;
3644 newarg = 1;
3645 *line = 0;
3646 } else if (*line == ']') {
3647 if (ssl_e) {
3648 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003649 cfgerr = 1;
3650 break;
3651 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003652 if (!ssl_b) {
3653 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3654 cfgerr = 1;
3655 break;
3656 }
3657 ssl_e = arg;
3658 newarg = 1;
3659 *line = 0;
3660 } else if (newarg) {
3661 if (arg == MAX_CRT_ARGS) {
3662 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3663 cfgerr = 1;
3664 break;
3665 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003666 newarg = 0;
3667 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003668 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003669 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003670 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003671 if (cfgerr)
3672 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003673 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003674
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003675 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003676 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003677 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003678
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003679 crt_path = args[0];
3680 if (*crt_path != '/' && global_ssl.crt_base) {
3681 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3682 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3683 crt_path, linenum, file);
3684 cfgerr = 1;
3685 break;
3686 }
3687 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3688 crt_path = path;
3689 }
3690
3691 ssl_conf = calloc(1, sizeof *ssl_conf);
3692 cur_arg = ssl_b ? ssl_b : 1;
3693 while (cur_arg < ssl_e) {
3694 newarg = 0;
3695 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3696 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3697 newarg = 1;
3698 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3699 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3700 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3701 args[cur_arg], linenum, file);
3702 cfgerr = 1;
3703 }
3704 cur_arg += 1 + ssl_bind_kws[i].skip;
3705 break;
3706 }
3707 }
3708 if (!cfgerr && !newarg) {
3709 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3710 args[cur_arg], linenum, file);
3711 cfgerr = 1;
3712 break;
3713 }
3714 }
3715 if (cfgerr) {
3716 ssl_sock_free_ssl_conf(ssl_conf);
3717 free(ssl_conf);
3718 ssl_conf = NULL;
3719 break;
3720 }
3721
3722 if (stat(crt_path, &buf) == 0) {
3723 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3724 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003725 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003726 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3727 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003728 }
3729
Willy Tarreauad1731d2013-04-02 17:35:58 +02003730 if (cfgerr) {
3731 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003732 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003733 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003734 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003735 fclose(f);
3736 return cfgerr;
3737}
3738
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003739/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003740static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003741ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003742{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003743 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003744 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003745 SSL_OP_ALL | /* all known workarounds for bugs */
3746 SSL_OP_NO_SSLv2 |
3747 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003748 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003749 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003750 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003751 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003752 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003753 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003754 SSL_MODE_ENABLE_PARTIAL_WRITE |
3755 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003756 SSL_MODE_RELEASE_BUFFERS |
3757 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003758 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003759 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003760 int flags = MC_SSL_O_ALL;
3761 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003762
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003763 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003764 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003765
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003766 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003767 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3768 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3769 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003770 else
3771 flags = conf_ssl_methods->flags;
3772
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003773 min = conf_ssl_methods->min;
3774 max = conf_ssl_methods->max;
3775 /* start with TLSv10 to remove SSLv3 per default */
3776 if (!min && (!max || max >= CONF_TLSV10))
3777 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003778 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003779 if (min)
3780 flags |= (methodVersions[min].flag - 1);
3781 if (max)
3782 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003783 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003784 min = max = CONF_TLSV_NONE;
3785 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003786 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003787 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003788 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003789 if (min) {
3790 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003791 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3792 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3793 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3794 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003795 hole = 0;
3796 }
3797 max = i;
3798 }
3799 else {
3800 min = max = i;
3801 }
3802 }
3803 else {
3804 if (min)
3805 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003806 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003807 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003808 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3809 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003810 cfgerr += 1;
3811 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003812 /* save real min/max in bind_conf */
3813 conf_ssl_methods->min = min;
3814 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003815
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003816#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003817 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003818 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003819 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003820 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003821 else
3822 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3823 if (flags & methodVersions[i].flag)
3824 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003825#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003826 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003827 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3828 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003829#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003830
3831 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3832 options |= SSL_OP_NO_TICKET;
3833 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3834 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3835 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003836
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003837#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003838 if (global_ssl.async)
3839 mode |= SSL_MODE_ASYNC;
3840#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003841 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003842 if (global_ssl.life_time)
3843 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003844
3845#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3846#ifdef OPENSSL_IS_BORINGSSL
3847 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3848 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003849#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3850 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3851 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003852#else
3853 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003854#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003855 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003856#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003857 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003858}
3859
William Lallemand4f45bb92017-10-30 20:08:51 +01003860
3861static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3862{
3863 if (first == block) {
3864 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3865 if (first->len > 0)
3866 sh_ssl_sess_tree_delete(sh_ssl_sess);
3867 }
3868}
3869
3870/* return first block from sh_ssl_sess */
3871static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3872{
3873 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3874
3875}
3876
3877/* store a session into the cache
3878 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3879 * data: asn1 encoded session
3880 * data_len: asn1 encoded session length
3881 * Returns 1 id session was stored (else 0)
3882 */
3883static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3884{
3885 struct shared_block *first;
3886 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3887
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003888 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003889 if (!first) {
3890 /* Could not retrieve enough free blocks to store that session */
3891 return 0;
3892 }
3893
3894 /* STORE the key in the first elem */
3895 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3896 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3897 first->len = sizeof(struct sh_ssl_sess_hdr);
3898
3899 /* it returns the already existing node
3900 or current node if none, never returns null */
3901 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3902 if (oldsh_ssl_sess != sh_ssl_sess) {
3903 /* NOTE: Row couldn't be in use because we lock read & write function */
3904 /* release the reserved row */
3905 shctx_row_dec_hot(ssl_shctx, first);
3906 /* replace the previous session already in the tree */
3907 sh_ssl_sess = oldsh_ssl_sess;
3908 /* ignore the previous session data, only use the header */
3909 first = sh_ssl_sess_first_block(sh_ssl_sess);
3910 shctx_row_inc_hot(ssl_shctx, first);
3911 first->len = sizeof(struct sh_ssl_sess_hdr);
3912 }
3913
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003914 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003915 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003916 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003917 }
3918
3919 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003920
3921 return 1;
3922}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003923
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003924/* SSL callback used when a new session is created while connecting to a server */
3925static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3926{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003927 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003928 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003929
Willy Tarreau07d94e42018-09-20 10:57:52 +02003930 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003931
Olivier Houcharde6060c52017-11-16 17:42:52 +01003932 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3933 int len;
3934 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003935
Olivier Houcharde6060c52017-11-16 17:42:52 +01003936 len = i2d_SSL_SESSION(sess, NULL);
3937 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3938 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3939 } else {
3940 free(s->ssl_ctx.reused_sess[tid].ptr);
3941 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3942 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3943 }
3944 if (s->ssl_ctx.reused_sess[tid].ptr) {
3945 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3946 &ptr);
3947 }
3948 } else {
3949 free(s->ssl_ctx.reused_sess[tid].ptr);
3950 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3951 }
3952
3953 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003954}
3955
Olivier Houcharde6060c52017-11-16 17:42:52 +01003956
William Lallemanded0b5ad2017-10-30 19:36:36 +01003957/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003958int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003959{
3960 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3961 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3962 unsigned char *p;
3963 int data_len;
3964 unsigned int sid_length, sid_ctx_length;
3965 const unsigned char *sid_data;
3966 const unsigned char *sid_ctx_data;
3967
3968 /* Session id is already stored in to key and session id is known
3969 * so we dont store it to keep size.
3970 */
3971
3972 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3973 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3974 SSL_SESSION_set1_id(sess, sid_data, 0);
3975 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3976
3977 /* check if buffer is large enough for the ASN1 encoded session */
3978 data_len = i2d_SSL_SESSION(sess, NULL);
3979 if (data_len > SHSESS_MAX_DATA_LEN)
3980 goto err;
3981
3982 p = encsess;
3983
3984 /* process ASN1 session encoding before the lock */
3985 i2d_SSL_SESSION(sess, &p);
3986
3987 memcpy(encid, sid_data, sid_length);
3988 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3989 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3990
William Lallemanda3c77cf2017-10-30 23:44:40 +01003991 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003992 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003993 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003994 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003995err:
3996 /* reset original length values */
3997 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3998 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3999
4000 return 0; /* do not increment session reference count */
4001}
4002
4003/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004004SSL_SESSION *sh_ssl_sess_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004005{
William Lallemand4f45bb92017-10-30 20:08:51 +01004006 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004007 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4008 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004009 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004010 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004011
4012 global.shctx_lookups++;
4013
4014 /* allow the session to be freed automatically by openssl */
4015 *do_copy = 0;
4016
4017 /* tree key is zeros padded sessionid */
4018 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4019 memcpy(tmpkey, key, key_len);
4020 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4021 key = tmpkey;
4022 }
4023
4024 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004025 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004026
4027 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004028 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4029 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004030 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004031 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004032 global.shctx_misses++;
4033 return NULL;
4034 }
4035
William Lallemand4f45bb92017-10-30 20:08:51 +01004036 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4037 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004038
William Lallemand4f45bb92017-10-30 20:08:51 +01004039 shctx_row_data_get(ssl_shctx, first, data, sizeof(struct sh_ssl_sess_hdr), first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004040
William Lallemanda3c77cf2017-10-30 23:44:40 +01004041 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004042
4043 /* decode ASN1 session */
4044 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004045 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004046 /* Reset session id and session id contenxt */
4047 if (sess) {
4048 SSL_SESSION_set1_id(sess, key, key_len);
4049 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4050 }
4051
4052 return sess;
4053}
4054
William Lallemand4f45bb92017-10-30 20:08:51 +01004055
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004057void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004058{
William Lallemand4f45bb92017-10-30 20:08:51 +01004059 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004060 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4061 unsigned int sid_length;
4062 const unsigned char *sid_data;
4063 (void)ctx;
4064
4065 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4066 /* tree key is zeros padded sessionid */
4067 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4068 memcpy(tmpkey, sid_data, sid_length);
4069 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4070 sid_data = tmpkey;
4071 }
4072
William Lallemanda3c77cf2017-10-30 23:44:40 +01004073 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004074
4075 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004076 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4077 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004078 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004079 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004080 }
4081
4082 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004083 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004084}
4085
4086/* Set session cache mode to server and disable openssl internal cache.
4087 * Set shared cache callbacks on an ssl context.
4088 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004089void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004090{
4091 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4092
4093 if (!ssl_shctx) {
4094 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4095 return;
4096 }
4097
4098 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4099 SSL_SESS_CACHE_NO_INTERNAL |
4100 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4101
4102 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004103 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4104 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4105 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004106}
4107
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004108int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4109{
4110 struct proxy *curproxy = bind_conf->frontend;
4111 int cfgerr = 0;
4112 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004113 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004114 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004115#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4116 const char *conf_ciphersuites;
4117#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004118 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004119
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004120 if (ssl_conf) {
4121 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4122 int i, min, max;
4123 int flags = MC_SSL_O_ALL;
4124
4125 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004126 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4127 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004128 if (min)
4129 flags |= (methodVersions[min].flag - 1);
4130 if (max)
4131 flags |= ~((methodVersions[max].flag << 1) - 1);
4132 min = max = CONF_TLSV_NONE;
4133 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4134 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4135 if (min)
4136 max = i;
4137 else
4138 min = max = i;
4139 }
4140 /* save real min/max */
4141 conf_ssl_methods->min = min;
4142 conf_ssl_methods->max = max;
4143 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004144 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4145 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004146 cfgerr += 1;
4147 }
4148 }
4149
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004150 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004151 case SSL_SOCK_VERIFY_NONE:
4152 verify = SSL_VERIFY_NONE;
4153 break;
4154 case SSL_SOCK_VERIFY_OPTIONAL:
4155 verify = SSL_VERIFY_PEER;
4156 break;
4157 case SSL_SOCK_VERIFY_REQUIRED:
4158 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4159 break;
4160 }
4161 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4162 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004163 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4164 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4165 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004166 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004167 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004168 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4169 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004170 cfgerr++;
4171 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004172 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4173 /* set CA names for client cert request, function returns void */
4174 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4175 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004176 }
Emeric Brun850efd52014-01-29 12:24:34 +01004177 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004178 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4179 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004180 cfgerr++;
4181 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004182#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004183 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004184 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4185
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004186 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004187 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4188 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004189 cfgerr++;
4190 }
Emeric Brun561e5742012-10-02 15:20:55 +02004191 else {
4192 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4193 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004194 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004195#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004196 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004197 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004198#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004199 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004200 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004201 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4202 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004203 cfgerr++;
4204 }
4205 }
4206#endif
4207
William Lallemand4f45bb92017-10-30 20:08:51 +01004208 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004209 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4210 if (conf_ciphers &&
4211 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004212 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4213 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004214 cfgerr++;
4215 }
4216
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004217#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4218 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4219 if (conf_ciphersuites &&
4220 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4221 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4222 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4223 cfgerr++;
4224 }
4225#endif
4226
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004227#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004228 /* If tune.ssl.default-dh-param has not been set,
4229 neither has ssl-default-dh-file and no static DH
4230 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004231 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004232 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004233 (ssl_dh_ptr_index == -1 ||
4234 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004235 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4236 const SSL_CIPHER * cipher = NULL;
4237 char cipher_description[128];
4238 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4239 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4240 which is not ephemeral DH. */
4241 const char dhe_description[] = " Kx=DH ";
4242 const char dhe_export_description[] = " Kx=DH(";
4243 int idx = 0;
4244 int dhe_found = 0;
4245 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004246
Remi Gacogne23d5d372014-10-10 17:04:26 +02004247 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004248
Remi Gacogne23d5d372014-10-10 17:04:26 +02004249 if (ssl) {
4250 ciphers = SSL_get_ciphers(ssl);
4251
4252 if (ciphers) {
4253 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4254 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4255 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4256 if (strstr(cipher_description, dhe_description) != NULL ||
4257 strstr(cipher_description, dhe_export_description) != NULL) {
4258 dhe_found = 1;
4259 break;
4260 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004261 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004262 }
4263 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004264 SSL_free(ssl);
4265 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004266 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004267
Lukas Tribus90132722014-08-18 00:56:33 +02004268 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004269 ha_warning("Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.\n");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004270 }
4271
Willy Tarreauef934602016-12-22 23:12:01 +01004272 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004273 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004274
Willy Tarreauef934602016-12-22 23:12:01 +01004275 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004276 if (local_dh_1024 == NULL) {
4277 local_dh_1024 = ssl_get_dh_1024();
4278 }
Willy Tarreauef934602016-12-22 23:12:01 +01004279 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004280 if (local_dh_2048 == NULL) {
4281 local_dh_2048 = ssl_get_dh_2048();
4282 }
Willy Tarreauef934602016-12-22 23:12:01 +01004283 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004284 if (local_dh_4096 == NULL) {
4285 local_dh_4096 = ssl_get_dh_4096();
4286 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004287 }
4288 }
4289 }
4290#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004291
Emeric Brunfc0421f2012-09-07 17:30:07 +02004292 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004293#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004294 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004295#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004296
Bernard Spil13c53f82018-02-15 13:34:58 +01004297#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004298 ssl_conf_cur = NULL;
4299 if (ssl_conf && ssl_conf->npn_str)
4300 ssl_conf_cur = ssl_conf;
4301 else if (bind_conf->ssl_conf.npn_str)
4302 ssl_conf_cur = &bind_conf->ssl_conf;
4303 if (ssl_conf_cur)
4304 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004305#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004306#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004307 ssl_conf_cur = NULL;
4308 if (ssl_conf && ssl_conf->alpn_str)
4309 ssl_conf_cur = ssl_conf;
4310 else if (bind_conf->ssl_conf.alpn_str)
4311 ssl_conf_cur = &bind_conf->ssl_conf;
4312 if (ssl_conf_cur)
4313 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004314#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004315#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4316 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4317 if (conf_curves) {
4318 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004319 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4320 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004321 cfgerr++;
4322 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004323#if defined(SSL_CTX_set_ecdh_auto)
4324 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4325#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004326 }
4327#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004328#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004329 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004330 int i;
4331 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004332#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004333 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004334 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4335 NULL);
4336
4337 if (ecdhe == NULL) {
4338 SSL_CTX_set_dh_auto(ctx, 1);
4339 return cfgerr;
4340 }
4341#else
4342 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4343 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4344 ECDHE_DEFAULT_CURVE);
4345#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004346
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004347 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004348 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004349 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4350 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004351 cfgerr++;
4352 }
4353 else {
4354 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4355 EC_KEY_free(ecdh);
4356 }
4357 }
4358#endif
4359
Emeric Brunfc0421f2012-09-07 17:30:07 +02004360 return cfgerr;
4361}
4362
Evan Broderbe554312013-06-27 00:05:25 -07004363static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4364{
4365 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4366 size_t prefixlen, suffixlen;
4367
4368 /* Trivial case */
4369 if (strcmp(pattern, hostname) == 0)
4370 return 1;
4371
Evan Broderbe554312013-06-27 00:05:25 -07004372 /* The rest of this logic is based on RFC 6125, section 6.4.3
4373 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4374
Emeric Bruna848dae2013-10-08 11:27:28 +02004375 pattern_wildcard = NULL;
4376 pattern_left_label_end = pattern;
4377 while (*pattern_left_label_end != '.') {
4378 switch (*pattern_left_label_end) {
4379 case 0:
4380 /* End of label not found */
4381 return 0;
4382 case '*':
4383 /* If there is more than one wildcards */
4384 if (pattern_wildcard)
4385 return 0;
4386 pattern_wildcard = pattern_left_label_end;
4387 break;
4388 }
4389 pattern_left_label_end++;
4390 }
4391
4392 /* If it's not trivial and there is no wildcard, it can't
4393 * match */
4394 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004395 return 0;
4396
4397 /* Make sure all labels match except the leftmost */
4398 hostname_left_label_end = strchr(hostname, '.');
4399 if (!hostname_left_label_end
4400 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4401 return 0;
4402
4403 /* Make sure the leftmost label of the hostname is long enough
4404 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004405 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004406 return 0;
4407
4408 /* Finally compare the string on either side of the
4409 * wildcard */
4410 prefixlen = pattern_wildcard - pattern;
4411 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004412 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4413 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004414 return 0;
4415
4416 return 1;
4417}
4418
4419static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4420{
4421 SSL *ssl;
4422 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004423 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004424 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004425
4426 int depth;
4427 X509 *cert;
4428 STACK_OF(GENERAL_NAME) *alt_names;
4429 int i;
4430 X509_NAME *cert_subject;
4431 char *str;
4432
4433 if (ok == 0)
4434 return ok;
4435
4436 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004437 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004438
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004439 /* We're checking if the provided hostnames match the desired one. The
4440 * desired hostname comes from the SNI we presented if any, or if not
4441 * provided then it may have been explicitly stated using a "verifyhost"
4442 * directive. If neither is set, we don't care about the name so the
4443 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004444 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004445 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004446 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004447 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004448 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004449 if (!servername)
4450 return ok;
4451 }
Evan Broderbe554312013-06-27 00:05:25 -07004452
4453 /* We only need to verify the CN on the actual server cert,
4454 * not the indirect CAs */
4455 depth = X509_STORE_CTX_get_error_depth(ctx);
4456 if (depth != 0)
4457 return ok;
4458
4459 /* At this point, the cert is *not* OK unless we can find a
4460 * hostname match */
4461 ok = 0;
4462
4463 cert = X509_STORE_CTX_get_current_cert(ctx);
4464 /* It seems like this might happen if verify peer isn't set */
4465 if (!cert)
4466 return ok;
4467
4468 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4469 if (alt_names) {
4470 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4471 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4472 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004473#if OPENSSL_VERSION_NUMBER < 0x00907000L
4474 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4475#else
Evan Broderbe554312013-06-27 00:05:25 -07004476 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004477#endif
Evan Broderbe554312013-06-27 00:05:25 -07004478 ok = ssl_sock_srv_hostcheck(str, servername);
4479 OPENSSL_free(str);
4480 }
4481 }
4482 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004483 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004484 }
4485
4486 cert_subject = X509_get_subject_name(cert);
4487 i = -1;
4488 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4489 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004490 ASN1_STRING *value;
4491 value = X509_NAME_ENTRY_get_data(entry);
4492 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004493 ok = ssl_sock_srv_hostcheck(str, servername);
4494 OPENSSL_free(str);
4495 }
4496 }
4497
Willy Tarreau71d058c2017-07-26 20:09:56 +02004498 /* report the mismatch and indicate if SNI was used or not */
4499 if (!ok && !conn->err_code)
4500 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004501 return ok;
4502}
4503
Emeric Brun94324a42012-10-11 14:00:19 +02004504/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004505int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004506{
Willy Tarreau03209342016-12-22 17:08:28 +01004507 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004508 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004509 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004510 SSL_OP_ALL | /* all known workarounds for bugs */
4511 SSL_OP_NO_SSLv2 |
4512 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004513 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004514 SSL_MODE_ENABLE_PARTIAL_WRITE |
4515 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004516 SSL_MODE_RELEASE_BUFFERS |
4517 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004518 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004519 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004520 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004521 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004522 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004523
Thierry Fournier383085f2013-01-24 14:15:43 +01004524 /* Make sure openssl opens /dev/urandom before the chroot */
4525 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004526 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004527 cfgerr++;
4528 }
4529
Willy Tarreaufce03112015-01-15 21:32:40 +01004530 /* Automatic memory computations need to know we use SSL there */
4531 global.ssl_used_backend = 1;
4532
4533 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004534 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004535 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004536 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4537 curproxy->id, srv->id,
4538 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004539 cfgerr++;
4540 return cfgerr;
4541 }
4542 }
Emeric Brun94324a42012-10-11 14:00:19 +02004543 if (srv->use_ssl)
4544 srv->xprt = &ssl_sock;
4545 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004546 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004547
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004548 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004549 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004550 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4551 proxy_type_str(curproxy), curproxy->id,
4552 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004553 cfgerr++;
4554 return cfgerr;
4555 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004556
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004557 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004558 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4559 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4560 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004561 else
4562 flags = conf_ssl_methods->flags;
4563
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004564 /* Real min and max should be determinate with configuration and openssl's capabilities */
4565 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004566 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004567 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004568 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004569
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004570 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004571 min = max = CONF_TLSV_NONE;
4572 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004573 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004574 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004575 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004576 if (min) {
4577 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004578 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4579 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4580 proxy_type_str(curproxy), curproxy->id, srv->id,
4581 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004582 hole = 0;
4583 }
4584 max = i;
4585 }
4586 else {
4587 min = max = i;
4588 }
4589 }
4590 else {
4591 if (min)
4592 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004593 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004594 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004595 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4596 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004597 cfgerr += 1;
4598 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004599
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004600#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004601 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004602 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004603 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004604 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004605 else
4606 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4607 if (flags & methodVersions[i].flag)
4608 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004609#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004610 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004611 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4612 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004613#endif
4614
4615 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4616 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004617 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004618
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004619#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004620 if (global_ssl.async)
4621 mode |= SSL_MODE_ASYNC;
4622#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004623 SSL_CTX_set_mode(ctx, mode);
4624 srv->ssl_ctx.ctx = ctx;
4625
Emeric Bruna7aa3092012-10-26 12:58:00 +02004626 if (srv->ssl_ctx.client_crt) {
4627 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004628 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4629 proxy_type_str(curproxy), curproxy->id,
4630 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004631 cfgerr++;
4632 }
4633 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004634 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4635 proxy_type_str(curproxy), curproxy->id,
4636 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004637 cfgerr++;
4638 }
4639 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004640 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4641 proxy_type_str(curproxy), curproxy->id,
4642 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004643 cfgerr++;
4644 }
4645 }
Emeric Brun94324a42012-10-11 14:00:19 +02004646
Emeric Brun850efd52014-01-29 12:24:34 +01004647 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4648 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004649 switch (srv->ssl_ctx.verify) {
4650 case SSL_SOCK_VERIFY_NONE:
4651 verify = SSL_VERIFY_NONE;
4652 break;
4653 case SSL_SOCK_VERIFY_REQUIRED:
4654 verify = SSL_VERIFY_PEER;
4655 break;
4656 }
Evan Broderbe554312013-06-27 00:05:25 -07004657 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004658 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004659 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004660 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004661 if (srv->ssl_ctx.ca_file) {
4662 /* load CAfile to verify */
4663 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004664 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4665 curproxy->id, srv->id,
4666 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004667 cfgerr++;
4668 }
4669 }
Emeric Brun850efd52014-01-29 12:24:34 +01004670 else {
4671 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004672 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
4673 curproxy->id, srv->id,
4674 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004675 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004676 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4677 curproxy->id, srv->id,
4678 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004679 cfgerr++;
4680 }
Emeric Brunef42d922012-10-11 16:11:36 +02004681#ifdef X509_V_FLAG_CRL_CHECK
4682 if (srv->ssl_ctx.crl_file) {
4683 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4684
4685 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004686 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4687 curproxy->id, srv->id,
4688 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004689 cfgerr++;
4690 }
4691 else {
4692 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4693 }
4694 }
4695#endif
4696 }
4697
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004698 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4699 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4700 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004701 if (srv->ssl_ctx.ciphers &&
4702 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004703 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4704 curproxy->id, srv->id,
4705 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004706 cfgerr++;
4707 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004708
4709#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4710 if (srv->ssl_ctx.ciphersuites &&
4711 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4712 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4713 curproxy->id, srv->id,
4714 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4715 cfgerr++;
4716 }
4717#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004718#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4719 if (srv->ssl_ctx.npn_str)
4720 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4721#endif
4722#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4723 if (srv->ssl_ctx.alpn_str)
4724 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4725#endif
4726
Emeric Brun94324a42012-10-11 14:00:19 +02004727
4728 return cfgerr;
4729}
4730
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004731/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004732 * be NULL, in which case nothing is done. Returns the number of errors
4733 * encountered.
4734 */
Willy Tarreau03209342016-12-22 17:08:28 +01004735int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004736{
4737 struct ebmb_node *node;
4738 struct sni_ctx *sni;
4739 int err = 0;
4740
Willy Tarreaufce03112015-01-15 21:32:40 +01004741 /* Automatic memory computations need to know we use SSL there */
4742 global.ssl_used_frontend = 1;
4743
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004744 /* Make sure openssl opens /dev/urandom before the chroot */
4745 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004746 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004747 err++;
4748 }
4749 /* Create initial_ctx used to start the ssl connection before do switchctx */
4750 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004751 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004752 /* It should not be necessary to call this function, but it's
4753 necessary first to check and move all initialisation related
4754 to initial_ctx in ssl_sock_initial_ctx. */
4755 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4756 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004757 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004758 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004759
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004760 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004761 while (node) {
4762 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004763 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4764 /* only initialize the CTX on its first occurrence and
4765 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004766 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004767 node = ebmb_next(node);
4768 }
4769
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004770 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004771 while (node) {
4772 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004773 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4774 /* only initialize the CTX on its first occurrence and
4775 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004776 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 node = ebmb_next(node);
4778 }
4779 return err;
4780}
4781
Willy Tarreau55d37912016-12-21 23:38:39 +01004782/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4783 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4784 * alerts are directly emitted since the rest of the stack does it below.
4785 */
4786int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4787{
4788 struct proxy *px = bind_conf->frontend;
4789 int alloc_ctx;
4790 int err;
4791
4792 if (!bind_conf->is_ssl) {
4793 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004794 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4795 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004796 }
4797 return 0;
4798 }
4799 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004800 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004801 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4802 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004803 }
4804 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004805 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4806 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004807 return -1;
4808 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004809 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004810 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004811 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004812 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004813 sizeof(*sh_ssl_sess_tree),
4814 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004815 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004816 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4817 ha_alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
4818 else
4819 ha_alert("Unable to allocate SSL session cache.\n");
4820 return -1;
4821 }
4822 /* free block callback */
4823 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4824 /* init the root tree within the extra space */
4825 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4826 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004827 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004828 err = 0;
4829 /* initialize all certificate contexts */
4830 err += ssl_sock_prepare_all_ctx(bind_conf);
4831
4832 /* initialize CA variables if the certificates generation is enabled */
4833 err += ssl_sock_load_ca(bind_conf);
4834
4835 return -err;
4836}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004837
4838/* release ssl context allocated for servers. */
4839void ssl_sock_free_srv_ctx(struct server *srv)
4840{
Olivier Houchardc7566002018-11-20 23:33:50 +01004841#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4842 if (srv->ssl_ctx.alpn_str)
4843 free(srv->ssl_ctx.alpn_str);
4844#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004845#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004846 if (srv->ssl_ctx.npn_str)
4847 free(srv->ssl_ctx.npn_str);
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004848 if (srv->ssl_ctx.ctx)
4849 SSL_CTX_free(srv->ssl_ctx.ctx);
Olivier Houchardc7566002018-11-20 23:33:50 +01004850#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004851}
4852
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004853/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004854 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4855 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004856void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004857{
4858 struct ebmb_node *node, *back;
4859 struct sni_ctx *sni;
4860
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004861 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004862 while (node) {
4863 sni = ebmb_entry(node, struct sni_ctx, name);
4864 back = ebmb_next(node);
4865 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004866 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004867 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004868 ssl_sock_free_ssl_conf(sni->conf);
4869 free(sni->conf);
4870 sni->conf = NULL;
4871 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004872 free(sni);
4873 node = back;
4874 }
4875
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004876 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004877 while (node) {
4878 sni = ebmb_entry(node, struct sni_ctx, name);
4879 back = ebmb_next(node);
4880 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004881 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004882 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004883 ssl_sock_free_ssl_conf(sni->conf);
4884 free(sni->conf);
4885 sni->conf = NULL;
4886 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004887 free(sni);
4888 node = back;
4889 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004890 SSL_CTX_free(bind_conf->initial_ctx);
4891 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004892 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004893 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004894}
4895
Willy Tarreau795cdab2016-12-22 17:30:54 +01004896/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4897void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4898{
4899 ssl_sock_free_ca(bind_conf);
4900 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004901 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004902 free(bind_conf->ca_sign_file);
4903 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004904 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004905 free(bind_conf->keys_ref->filename);
4906 free(bind_conf->keys_ref->tlskeys);
4907 LIST_DEL(&bind_conf->keys_ref->list);
4908 free(bind_conf->keys_ref);
4909 }
4910 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004911 bind_conf->ca_sign_pass = NULL;
4912 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004913}
4914
Christopher Faulet31af49d2015-06-09 17:29:50 +02004915/* Load CA cert file and private key used to generate certificates */
4916int
Willy Tarreau03209342016-12-22 17:08:28 +01004917ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004918{
Willy Tarreau03209342016-12-22 17:08:28 +01004919 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004920 FILE *fp;
4921 X509 *cacert = NULL;
4922 EVP_PKEY *capkey = NULL;
4923 int err = 0;
4924
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004925 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004926 return err;
4927
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004928#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004929 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004930 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004931 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004932 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004933 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004934 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004935#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004936
Christopher Faulet31af49d2015-06-09 17:29:50 +02004937 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004938 ha_alert("Proxy '%s': cannot enable certificate generation, "
4939 "no CA certificate File configured at [%s:%d].\n",
4940 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004941 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004942 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004943
4944 /* read in the CA certificate */
4945 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004946 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4947 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004948 goto load_error;
4949 }
4950 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004951 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4952 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004953 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004954 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004955 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004956 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004957 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4958 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004959 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004960 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004961
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004962 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004963 bind_conf->ca_sign_cert = cacert;
4964 bind_conf->ca_sign_pkey = capkey;
4965 return err;
4966
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004967 read_error:
4968 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004969 if (capkey) EVP_PKEY_free(capkey);
4970 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004971 load_error:
4972 bind_conf->generate_certs = 0;
4973 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004974 return err;
4975}
4976
4977/* Release CA cert and private key used to generate certificated */
4978void
4979ssl_sock_free_ca(struct bind_conf *bind_conf)
4980{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004981 if (bind_conf->ca_sign_pkey)
4982 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4983 if (bind_conf->ca_sign_cert)
4984 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004985 bind_conf->ca_sign_pkey = NULL;
4986 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004987}
4988
Emeric Brun46591952012-05-18 15:47:34 +02004989/*
4990 * This function is called if SSL * context is not yet allocated. The function
4991 * is designed to be called before any other data-layer operation and sets the
4992 * handshake flag on the connection. It is safe to call it multiple times.
4993 * It returns 0 on success and -1 in error case.
4994 */
4995static int ssl_sock_init(struct connection *conn)
4996{
4997 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004998 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004999 return 0;
5000
Willy Tarreau3c728722014-01-23 13:50:42 +01005001 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005002 return 0;
5003
Willy Tarreau20879a02012-12-03 16:32:10 +01005004 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5005 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005006 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005007 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005008
Emeric Brun46591952012-05-18 15:47:34 +02005009 /* If it is in client mode initiate SSL session
5010 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005011 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005012 int may_retry = 1;
5013
5014 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005015 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005016 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005017 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005018 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005019 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005020 goto retry_connect;
5021 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005022 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005023 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005024 }
Emeric Brun46591952012-05-18 15:47:34 +02005025
Emeric Brun46591952012-05-18 15:47:34 +02005026 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005027 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005028 SSL_free(conn->xprt_ctx);
5029 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005030 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005031 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005032 goto retry_connect;
5033 }
Emeric Brun55476152014-11-12 17:35:37 +01005034 conn->err_code = CO_ER_SSL_NO_MEM;
5035 return -1;
5036 }
Emeric Brun46591952012-05-18 15:47:34 +02005037
Evan Broderbe554312013-06-27 00:05:25 -07005038 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005039 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005040 SSL_free(conn->xprt_ctx);
5041 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005042 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005043 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005044 goto retry_connect;
5045 }
Emeric Brun55476152014-11-12 17:35:37 +01005046 conn->err_code = CO_ER_SSL_NO_MEM;
5047 return -1;
5048 }
5049
5050 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005051 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5052 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5053 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5054 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005055 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005056 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5057 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005058 } else if (sess) {
5059 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005060 }
5061 }
Evan Broderbe554312013-06-27 00:05:25 -07005062
Emeric Brun46591952012-05-18 15:47:34 +02005063 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005064 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005065
Emeric Brun7ad43e72018-10-10 14:51:02 +02005066 HA_ATOMIC_ADD(&sslconns, 1);
5067 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005068 return 0;
5069 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005070 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005071 int may_retry = 1;
5072
5073 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005074 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005075 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005076 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005077 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005078 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005079 goto retry_accept;
5080 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005081 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005082 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005083 }
Emeric Brun46591952012-05-18 15:47:34 +02005084
Emeric Brun46591952012-05-18 15:47:34 +02005085 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005086 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005087 SSL_free(conn->xprt_ctx);
5088 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005089 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005090 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005091 goto retry_accept;
5092 }
Emeric Brun55476152014-11-12 17:35:37 +01005093 conn->err_code = CO_ER_SSL_NO_MEM;
5094 return -1;
5095 }
Emeric Brun46591952012-05-18 15:47:34 +02005096
Emeric Brune1f38db2012-09-03 20:36:47 +02005097 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005098 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005099 SSL_free(conn->xprt_ctx);
5100 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005101 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005102 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005103 goto retry_accept;
5104 }
Emeric Brun55476152014-11-12 17:35:37 +01005105 conn->err_code = CO_ER_SSL_NO_MEM;
5106 return -1;
5107 }
5108
5109 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005110
Emeric Brun46591952012-05-18 15:47:34 +02005111 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005112 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005113#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005114 conn->flags |= CO_FL_EARLY_SSL_HS;
5115#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005116
Emeric Brun7ad43e72018-10-10 14:51:02 +02005117 HA_ATOMIC_ADD(&sslconns, 1);
5118 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005119 return 0;
5120 }
5121 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005122 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005123 return -1;
5124}
5125
5126
5127/* This is the callback which is used when an SSL handshake is pending. It
5128 * updates the FD status if it wants some polling before being called again.
5129 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5130 * otherwise it returns non-zero and removes itself from the connection's
5131 * flags (the bit is provided in <flag> by the caller).
5132 */
5133int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5134{
5135 int ret;
5136
Willy Tarreau3c728722014-01-23 13:50:42 +01005137 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005138 return 0;
5139
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005140 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005141 goto out_error;
5142
Olivier Houchardc2aae742017-09-22 18:26:28 +02005143#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5144 /*
5145 * Check if we have early data. If we do, we have to read them
5146 * before SSL_do_handshake() is called, And there's no way to
5147 * detect early data, except to try to read them
5148 */
5149 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5150 size_t read_data;
5151
5152 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5153 1, &read_data);
5154 if (ret == SSL_READ_EARLY_DATA_ERROR)
5155 goto check_error;
5156 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5157 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5158 return 1;
5159 } else
5160 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5161 }
5162#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005163 /* If we use SSL_do_handshake to process a reneg initiated by
5164 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5165 * Usually SSL_write and SSL_read are used and process implicitly
5166 * the reneg handshake.
5167 * Here we use SSL_peek as a workaround for reneg.
5168 */
5169 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5170 char c;
5171
5172 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5173 if (ret <= 0) {
5174 /* handshake may have not been completed, let's find why */
5175 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005176
Emeric Brun674b7432012-11-08 19:21:55 +01005177 if (ret == SSL_ERROR_WANT_WRITE) {
5178 /* SSL handshake needs to write, L4 connection may not be ready */
5179 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005180 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005181 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005182 return 0;
5183 }
5184 else if (ret == SSL_ERROR_WANT_READ) {
5185 /* handshake may have been completed but we have
5186 * no more data to read.
5187 */
5188 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5189 ret = 1;
5190 goto reneg_ok;
5191 }
5192 /* SSL handshake needs to read, L4 connection is ready */
5193 if (conn->flags & CO_FL_WAIT_L4_CONN)
5194 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5195 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005196 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005197 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005198 return 0;
5199 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005200#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005201 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005202 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005203 return 0;
5204 }
5205#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005206 else if (ret == SSL_ERROR_SYSCALL) {
5207 /* if errno is null, then connection was successfully established */
5208 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5209 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005210 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005211#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005212 conn->err_code = CO_ER_SSL_HANDSHAKE;
5213#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005214 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005215#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005216 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5217 empty_handshake = state == TLS_ST_BEFORE;
5218#else
5219 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5220#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005221 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005222 if (!errno) {
5223 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5224 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5225 else
5226 conn->err_code = CO_ER_SSL_EMPTY;
5227 }
5228 else {
5229 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5230 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5231 else
5232 conn->err_code = CO_ER_SSL_ABORT;
5233 }
5234 }
5235 else {
5236 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5237 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005238 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005239 conn->err_code = CO_ER_SSL_HANDSHAKE;
5240 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005241#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005242 }
Emeric Brun674b7432012-11-08 19:21:55 +01005243 goto out_error;
5244 }
5245 else {
5246 /* Fail on all other handshake errors */
5247 /* Note: OpenSSL may leave unread bytes in the socket's
5248 * buffer, causing an RST to be emitted upon close() on
5249 * TCP sockets. We first try to drain possibly pending
5250 * data to avoid this as much as possible.
5251 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005252 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005253 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005254 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5255 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005256 goto out_error;
5257 }
5258 }
5259 /* read some data: consider handshake completed */
5260 goto reneg_ok;
5261 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005262 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005263check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005264 if (ret != 1) {
5265 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005266 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005267
5268 if (ret == SSL_ERROR_WANT_WRITE) {
5269 /* SSL handshake needs to write, L4 connection may not be ready */
5270 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005271 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005272 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005273 return 0;
5274 }
5275 else if (ret == SSL_ERROR_WANT_READ) {
5276 /* SSL handshake needs to read, L4 connection is ready */
5277 if (conn->flags & CO_FL_WAIT_L4_CONN)
5278 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5279 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005280 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005281 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005282 return 0;
5283 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005284#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005285 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005286 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005287 return 0;
5288 }
5289#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005290 else if (ret == SSL_ERROR_SYSCALL) {
5291 /* if errno is null, then connection was successfully established */
5292 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5293 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005294 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005295#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005296 conn->err_code = CO_ER_SSL_HANDSHAKE;
5297#else
5298 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005299#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005300 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5301 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005302#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005303 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005304#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005305 if (empty_handshake) {
5306 if (!errno) {
5307 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5308 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5309 else
5310 conn->err_code = CO_ER_SSL_EMPTY;
5311 }
5312 else {
5313 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5314 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5315 else
5316 conn->err_code = CO_ER_SSL_ABORT;
5317 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005318 }
5319 else {
5320 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5321 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5322 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005323 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005324 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005325#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005326 }
Willy Tarreau89230192012-09-28 20:22:13 +02005327 goto out_error;
5328 }
Emeric Brun46591952012-05-18 15:47:34 +02005329 else {
5330 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005331 /* Note: OpenSSL may leave unread bytes in the socket's
5332 * buffer, causing an RST to be emitted upon close() on
5333 * TCP sockets. We first try to drain possibly pending
5334 * data to avoid this as much as possible.
5335 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005336 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005337 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005338 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5339 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005340 goto out_error;
5341 }
5342 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005343#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5344 else {
5345 /*
5346 * If the server refused the early data, we have to send a
5347 * 425 to the client, as we no longer have the data to sent
5348 * them again.
5349 */
5350 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5351 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5352 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5353 goto out_error;
5354 }
5355 }
5356 }
5357#endif
5358
Emeric Brun46591952012-05-18 15:47:34 +02005359
Emeric Brun674b7432012-11-08 19:21:55 +01005360reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005361
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005362#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005363 /* ASYNC engine API doesn't support moving read/write
5364 * buffers. So we disable ASYNC mode right after
5365 * the handshake to avoid buffer oveflows.
5366 */
5367 if (global_ssl.async)
5368 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5369#endif
Emeric Brun46591952012-05-18 15:47:34 +02005370 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005371 if (!SSL_session_reused(conn->xprt_ctx)) {
5372 if (objt_server(conn->target)) {
5373 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5374 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5375 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005376 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005377 else {
5378 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5379 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5380 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5381 }
Emeric Brun46591952012-05-18 15:47:34 +02005382 }
5383
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005384#ifdef OPENSSL_IS_BORINGSSL
5385 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5386 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5387#endif
Emeric Brun46591952012-05-18 15:47:34 +02005388 /* The connection is now established at both layers, it's time to leave */
5389 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5390 return 1;
5391
5392 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005393 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005394 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005395 ERR_clear_error();
5396
Emeric Brun9fa89732012-10-04 17:09:56 +02005397 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005398 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5399 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5400 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005401 }
5402
Emeric Brun46591952012-05-18 15:47:34 +02005403 /* Fail on all other handshake errors */
5404 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005405 if (!conn->err_code)
5406 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005407 return 0;
5408}
5409
5410/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005411 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005412 * buffer wraps, in which case a second call may be performed. The connection's
5413 * flags are updated with whatever special event is detected (error, read0,
5414 * empty). The caller is responsible for taking care of those events and
5415 * avoiding the call if inappropriate. The function does not call the
5416 * connection's polling update function, so the caller is responsible for this.
5417 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005418static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005419{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005420 ssize_t ret;
5421 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005422
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005423 conn_refresh_polling_flags(conn);
5424
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005425 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005426 goto out_error;
5427
5428 if (conn->flags & CO_FL_HANDSHAKE)
5429 /* a handshake was requested */
5430 return 0;
5431
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005432 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005433
5434 /* read the largest possible block. For this, we perform only one call
5435 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5436 * in which case we accept to do it once again. A new attempt is made on
5437 * EINTR too.
5438 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005439 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005440 int need_out = 0;
5441
Willy Tarreau591d4452018-06-15 17:21:00 +02005442 try = b_contig_space(buf);
5443 if (!try)
5444 break;
5445
Willy Tarreauabf08d92014-01-14 11:31:27 +01005446 if (try > count)
5447 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005448
Olivier Houchardc2aae742017-09-22 18:26:28 +02005449 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5450 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005451 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005452 done++;
5453 try--;
5454 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005455 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005456 conn->tmp_early_data = -1;
5457 continue;
5458 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005459
Olivier Houchardc2aae742017-09-22 18:26:28 +02005460#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5461 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5462 size_t read_length;
5463
5464 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005465 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005466 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5467 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005468 conn->flags |= CO_FL_EARLY_DATA;
5469 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5470 ret == SSL_READ_EARLY_DATA_FINISH) {
5471 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5472 /*
5473 * We're done reading the early data,
5474 * let's make the handshake
5475 */
5476 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5477 conn->flags |= CO_FL_SSL_WAIT_HS;
5478 need_out = 1;
5479 if (read_length == 0)
5480 break;
5481 }
5482 ret = read_length;
5483 }
5484 } else
5485#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005486 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005487#ifdef OPENSSL_IS_BORINGSSL
5488 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5489 if (SSL_in_early_data(conn->xprt_ctx)) {
5490 if (ret > 0)
5491 conn->flags |= CO_FL_EARLY_DATA;
5492 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005493 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005494 }
5495 }
5496#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005497 if (conn->flags & CO_FL_ERROR) {
5498 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005499 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005500 }
Emeric Brun46591952012-05-18 15:47:34 +02005501 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005502 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005503 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005504 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005505 }
Emeric Brun46591952012-05-18 15:47:34 +02005506 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005507 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005508 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005509 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005510 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005511 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005512#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005513 /* Async mode can be re-enabled, because we're leaving data state.*/
5514 if (global_ssl.async)
5515 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5516#endif
Emeric Brun46591952012-05-18 15:47:34 +02005517 break;
5518 }
5519 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005520 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5521 /* handshake is running, and it may need to re-enable read */
5522 conn->flags |= CO_FL_SSL_WAIT_HS;
5523 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005524#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005525 /* Async mode can be re-enabled, because we're leaving data state.*/
5526 if (global_ssl.async)
5527 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5528#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005529 break;
5530 }
Emeric Brun46591952012-05-18 15:47:34 +02005531 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005532 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005533 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005534 } else if (ret == SSL_ERROR_ZERO_RETURN)
5535 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005536 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5537 * stack before shutting down the connection for
5538 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005539 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5540 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005541 /* otherwise it's a real error */
5542 goto out_error;
5543 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005544 if (need_out)
5545 break;
Emeric Brun46591952012-05-18 15:47:34 +02005546 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005547 leave:
5548 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005549 return done;
5550
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005551 clear_ssl_error:
5552 /* Clear openssl global errors stack */
5553 ssl_sock_dump_errors(conn);
5554 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005555 read0:
5556 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005557 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005558
Emeric Brun46591952012-05-18 15:47:34 +02005559 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005560 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005561 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005562 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005563 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005564 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005565}
5566
5567
Willy Tarreau787db9a2018-06-14 18:31:46 +02005568/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5569 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5570 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005571 * Only one call to send() is performed, unless the buffer wraps, in which case
5572 * a second call may be performed. The connection's flags are updated with
5573 * whatever special event is detected (error, empty). The caller is responsible
5574 * for taking care of those events and avoiding the call if inappropriate. The
5575 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005576 * is responsible for this. The buffer's output is not adjusted, it's up to the
5577 * caller to take care of this. It's up to the caller to update the buffer's
5578 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005579 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005580static size_t ssl_sock_from_buf(struct connection *conn, const struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005581{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005582 ssize_t ret;
5583 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005584
5585 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005586 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005587
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005588 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005589 goto out_error;
5590
5591 if (conn->flags & CO_FL_HANDSHAKE)
5592 /* a handshake was requested */
5593 return 0;
5594
5595 /* send the largest possible block. For this we perform only one call
5596 * to send() unless the buffer wraps and we exactly fill the first hunk,
5597 * in which case we accept to do it once again.
5598 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005599 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005600#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5601 size_t written_data;
5602#endif
5603
Willy Tarreau787db9a2018-06-14 18:31:46 +02005604 try = b_contig_data(buf, done);
5605 if (try > count)
5606 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005607
Willy Tarreau7bed9452014-02-02 02:00:24 +01005608 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005609 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005610 global_ssl.max_record && try > global_ssl.max_record) {
5611 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005612 }
5613 else {
5614 /* we need to keep the information about the fact that
5615 * we're not limiting the upcoming send(), because if it
5616 * fails, we'll have to retry with at least as many data.
5617 */
5618 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5619 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005620
Olivier Houchardc2aae742017-09-22 18:26:28 +02005621#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5622 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5623 unsigned int max_early;
5624
Olivier Houchard522eea72017-11-03 16:27:47 +01005625 if (objt_listener(conn->target))
5626 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5627 else {
5628 if (SSL_get0_session(conn->xprt_ctx))
5629 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5630 else
5631 max_early = 0;
5632 }
5633
Olivier Houchard90084a12017-11-23 18:21:29 +01005634 if (try + conn->sent_early_data > max_early) {
5635 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005636 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005637 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5638 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005639 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005640 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005641 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005642 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005643 if (ret == 1) {
5644 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005645 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005646 if (objt_server(conn->target)) {
5647 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5648 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5649 }
5650
Olivier Houchardc2aae742017-09-22 18:26:28 +02005651 }
5652
5653 } else
5654#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005655 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005656
Emeric Brune1f38db2012-09-03 20:36:47 +02005657 if (conn->flags & CO_FL_ERROR) {
5658 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005659 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005660 }
Emeric Brun46591952012-05-18 15:47:34 +02005661 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005662 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005663 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005664 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005665 }
5666 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005667 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005668
Emeric Brun46591952012-05-18 15:47:34 +02005669 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005670 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5671 /* handshake is running, and it may need to re-enable write */
5672 conn->flags |= CO_FL_SSL_WAIT_HS;
5673 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005674#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005675 /* Async mode can be re-enabled, because we're leaving data state.*/
5676 if (global_ssl.async)
5677 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5678#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005679 break;
5680 }
Emeric Brun46591952012-05-18 15:47:34 +02005681 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005682 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005683 break;
5684 }
5685 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005686 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005687 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005688 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005689#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005690 /* Async mode can be re-enabled, because we're leaving data state.*/
5691 if (global_ssl.async)
5692 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5693#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005694 break;
5695 }
Emeric Brun46591952012-05-18 15:47:34 +02005696 goto out_error;
5697 }
5698 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005699 leave:
5700 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005701 return done;
5702
5703 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005704 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005705 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005706 ERR_clear_error();
5707
Emeric Brun46591952012-05-18 15:47:34 +02005708 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005709 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005710}
5711
Emeric Brun46591952012-05-18 15:47:34 +02005712static void ssl_sock_close(struct connection *conn) {
5713
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005714 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005715#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005716 if (global_ssl.async) {
5717 OSSL_ASYNC_FD all_fd[32], afd;
5718 size_t num_all_fds = 0;
5719 int i;
5720
5721 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5722 if (num_all_fds > 32) {
5723 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5724 return;
5725 }
5726
5727 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5728
5729 /* If an async job is pending, we must try to
5730 to catch the end using polling before calling
5731 SSL_free */
5732 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5733 for (i=0 ; i < num_all_fds ; i++) {
5734 /* switch on an handler designed to
5735 * handle the SSL_free
5736 */
5737 afd = all_fd[i];
5738 fdtab[afd].iocb = ssl_async_fd_free;
5739 fdtab[afd].owner = conn->xprt_ctx;
5740 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005741 /* To ensure that the fd cache won't be used
5742 * and we'll catch a real RD event.
5743 */
5744 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005745 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005746 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005747 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005748 return;
5749 }
Emeric Brun3854e012017-05-17 20:42:48 +02005750 /* Else we can remove the fds from the fdtab
5751 * and call SSL_free.
5752 * note: we do a fd_remove and not a delete
5753 * because the fd is owned by the engine.
5754 * the engine is responsible to close
5755 */
5756 for (i=0 ; i < num_all_fds ; i++)
5757 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005758 }
5759#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005760 SSL_free(conn->xprt_ctx);
5761 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005762 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005763 }
Emeric Brun46591952012-05-18 15:47:34 +02005764}
5765
5766/* This function tries to perform a clean shutdown on an SSL connection, and in
5767 * any case, flags the connection as reusable if no handshake was in progress.
5768 */
5769static void ssl_sock_shutw(struct connection *conn, int clean)
5770{
5771 if (conn->flags & CO_FL_HANDSHAKE)
5772 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005773 if (!clean)
5774 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005775 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005776 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005777 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005778 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005779 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005780 ERR_clear_error();
5781 }
Emeric Brun46591952012-05-18 15:47:34 +02005782}
5783
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005784/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005785int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005786{
5787 struct pkey_info *pkinfo;
5788 int bits = 0;
5789 int sig = TLSEXT_signature_anonymous;
5790 int len = -1;
5791
5792 if (!ssl_sock_is_ssl(conn))
5793 return 0;
5794
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005795 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005796 if (pkinfo) {
5797 sig = pkinfo->sig;
5798 bits = pkinfo->bits;
5799 } else {
5800 /* multicert and generated cert have no pkey info */
5801 X509 *crt;
5802 EVP_PKEY *pkey;
5803 crt = SSL_get_certificate(conn->xprt_ctx);
5804 if (!crt)
5805 return 0;
5806 pkey = X509_get_pubkey(crt);
5807 if (pkey) {
5808 bits = EVP_PKEY_bits(pkey);
5809 switch(EVP_PKEY_base_id(pkey)) {
5810 case EVP_PKEY_RSA:
5811 sig = TLSEXT_signature_rsa;
5812 break;
5813 case EVP_PKEY_EC:
5814 sig = TLSEXT_signature_ecdsa;
5815 break;
5816 case EVP_PKEY_DSA:
5817 sig = TLSEXT_signature_dsa;
5818 break;
5819 }
5820 EVP_PKEY_free(pkey);
5821 }
5822 }
5823
5824 switch(sig) {
5825 case TLSEXT_signature_rsa:
5826 len = chunk_printf(out, "RSA%d", bits);
5827 break;
5828 case TLSEXT_signature_ecdsa:
5829 len = chunk_printf(out, "EC%d", bits);
5830 break;
5831 case TLSEXT_signature_dsa:
5832 len = chunk_printf(out, "DSA%d", bits);
5833 break;
5834 default:
5835 return 0;
5836 }
5837 if (len < 0)
5838 return 0;
5839 return 1;
5840}
5841
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005842/* used for ppv2 cert signature (can be used for logging) */
5843const char *ssl_sock_get_cert_sig(struct connection *conn)
5844{
5845 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5846 X509 *crt;
5847
5848 if (!ssl_sock_is_ssl(conn))
5849 return NULL;
5850 crt = SSL_get_certificate(conn->xprt_ctx);
5851 if (!crt)
5852 return NULL;
5853 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5854 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5855}
5856
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005857/* used for ppv2 authority */
5858const char *ssl_sock_get_sni(struct connection *conn)
5859{
5860#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5861 if (!ssl_sock_is_ssl(conn))
5862 return NULL;
5863 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5864#else
5865 return 0;
5866#endif
5867}
5868
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005869/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005870const char *ssl_sock_get_cipher_name(struct connection *conn)
5871{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005872 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005873 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005874
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005875 return SSL_get_cipher_name(conn->xprt_ctx);
5876}
5877
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005878/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005879const char *ssl_sock_get_proto_version(struct connection *conn)
5880{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005881 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005882 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005883
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005884 return SSL_get_version(conn->xprt_ctx);
5885}
5886
Willy Tarreau8d598402012-10-22 17:58:39 +02005887/* Extract a serial from a cert, and copy it to a chunk.
5888 * Returns 1 if serial is found and copied, 0 if no serial found and
5889 * -1 if output is not large enough.
5890 */
5891static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005892ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005893{
5894 ASN1_INTEGER *serial;
5895
5896 serial = X509_get_serialNumber(crt);
5897 if (!serial)
5898 return 0;
5899
5900 if (out->size < serial->length)
5901 return -1;
5902
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005903 memcpy(out->area, serial->data, serial->length);
5904 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005905 return 1;
5906}
5907
Emeric Brun43e79582014-10-29 19:03:26 +01005908/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005909 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5910 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005911 */
5912static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005913ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005914{
5915 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005916 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005917
5918 len =i2d_X509(crt, NULL);
5919 if (len <= 0)
5920 return 1;
5921
5922 if (out->size < len)
5923 return -1;
5924
5925 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005926 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005927 return 1;
5928}
5929
Emeric Brunce5ad802012-10-22 14:11:22 +02005930
Willy Tarreau83061a82018-07-13 11:56:34 +02005931/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005932 * Returns 1 if serial is found and copied, 0 if no valid time found
5933 * and -1 if output is not large enough.
5934 */
5935static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005936ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005937{
5938 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5939 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5940
5941 if (gentm->length < 12)
5942 return 0;
5943 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5944 return 0;
5945 if (out->size < gentm->length-2)
5946 return -1;
5947
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005948 memcpy(out->area, gentm->data+2, gentm->length-2);
5949 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005950 return 1;
5951 }
5952 else if (tm->type == V_ASN1_UTCTIME) {
5953 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5954
5955 if (utctm->length < 10)
5956 return 0;
5957 if (utctm->data[0] >= 0x35)
5958 return 0;
5959 if (out->size < utctm->length)
5960 return -1;
5961
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005962 memcpy(out->area, utctm->data, utctm->length);
5963 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005964 return 1;
5965 }
5966
5967 return 0;
5968}
5969
Emeric Brun87855892012-10-17 17:39:35 +02005970/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5971 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5972 */
5973static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005974ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5975 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005976{
5977 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005978 ASN1_OBJECT *obj;
5979 ASN1_STRING *data;
5980 const unsigned char *data_ptr;
5981 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005982 int i, j, n;
5983 int cur = 0;
5984 const char *s;
5985 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005986 int name_count;
5987
5988 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005989
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005990 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005991 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005992 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005993 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005994 else
5995 j = i;
5996
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005997 ne = X509_NAME_get_entry(a, j);
5998 obj = X509_NAME_ENTRY_get_object(ne);
5999 data = X509_NAME_ENTRY_get_data(ne);
6000 data_ptr = ASN1_STRING_get0_data(data);
6001 data_len = ASN1_STRING_length(data);
6002 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006003 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006004 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006005 s = tmp;
6006 }
6007
6008 if (chunk_strcasecmp(entry, s) != 0)
6009 continue;
6010
6011 if (pos < 0)
6012 cur--;
6013 else
6014 cur++;
6015
6016 if (cur != pos)
6017 continue;
6018
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006019 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006020 return -1;
6021
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006022 memcpy(out->area, data_ptr, data_len);
6023 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006024 return 1;
6025 }
6026
6027 return 0;
6028
6029}
6030
6031/* Extract and format full DN from a X509_NAME and copy result into a chunk
6032 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6033 */
6034static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006035ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006036{
6037 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006038 ASN1_OBJECT *obj;
6039 ASN1_STRING *data;
6040 const unsigned char *data_ptr;
6041 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006042 int i, n, ln;
6043 int l = 0;
6044 const char *s;
6045 char *p;
6046 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006047 int name_count;
6048
6049
6050 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006051
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006052 out->data = 0;
6053 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006054 for (i = 0; i < name_count; i++) {
6055 ne = X509_NAME_get_entry(a, i);
6056 obj = X509_NAME_ENTRY_get_object(ne);
6057 data = X509_NAME_ENTRY_get_data(ne);
6058 data_ptr = ASN1_STRING_get0_data(data);
6059 data_len = ASN1_STRING_length(data);
6060 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006061 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006062 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006063 s = tmp;
6064 }
6065 ln = strlen(s);
6066
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006067 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006068 if (l > out->size)
6069 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006070 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006071
6072 *(p++)='/';
6073 memcpy(p, s, ln);
6074 p += ln;
6075 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006076 memcpy(p, data_ptr, data_len);
6077 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006078 }
6079
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006080 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006081 return 0;
6082
6083 return 1;
6084}
6085
Willy Tarreau119a4082016-12-22 21:58:38 +01006086/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6087 * to disable SNI.
6088 */
Willy Tarreau63076412015-07-10 11:33:32 +02006089void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6090{
6091#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006092 char *prev_name;
6093
Willy Tarreau63076412015-07-10 11:33:32 +02006094 if (!ssl_sock_is_ssl(conn))
6095 return;
6096
Willy Tarreau119a4082016-12-22 21:58:38 +01006097 /* if the SNI changes, we must destroy the reusable context so that a
6098 * new connection will present a new SNI. As an optimization we could
6099 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6100 * server.
6101 */
6102 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6103 if ((!prev_name && hostname) ||
6104 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6105 SSL_set_session(conn->xprt_ctx, NULL);
6106
Willy Tarreau63076412015-07-10 11:33:32 +02006107 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6108#endif
6109}
6110
Emeric Brun0abf8362014-06-24 18:26:41 +02006111/* Extract peer certificate's common name into the chunk dest
6112 * Returns
6113 * the len of the extracted common name
6114 * or 0 if no CN found in DN
6115 * or -1 on error case (i.e. no peer certificate)
6116 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006117int ssl_sock_get_remote_common_name(struct connection *conn,
6118 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006119{
6120 X509 *crt = NULL;
6121 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006122 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006123 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006124 .area = (char *)&find_cn,
6125 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006126 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006127 int result = -1;
David Safb76832014-05-08 23:42:08 -04006128
6129 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006130 goto out;
David Safb76832014-05-08 23:42:08 -04006131
6132 /* SSL_get_peer_certificate, it increase X509 * ref count */
6133 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6134 if (!crt)
6135 goto out;
6136
6137 name = X509_get_subject_name(crt);
6138 if (!name)
6139 goto out;
David Safb76832014-05-08 23:42:08 -04006140
Emeric Brun0abf8362014-06-24 18:26:41 +02006141 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6142out:
David Safb76832014-05-08 23:42:08 -04006143 if (crt)
6144 X509_free(crt);
6145
6146 return result;
6147}
6148
Dave McCowan328fb582014-07-30 10:39:13 -04006149/* returns 1 if client passed a certificate for this session, 0 if not */
6150int ssl_sock_get_cert_used_sess(struct connection *conn)
6151{
6152 X509 *crt = NULL;
6153
6154 if (!ssl_sock_is_ssl(conn))
6155 return 0;
6156
6157 /* SSL_get_peer_certificate, it increase X509 * ref count */
6158 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6159 if (!crt)
6160 return 0;
6161
6162 X509_free(crt);
6163 return 1;
6164}
6165
6166/* returns 1 if client passed a certificate for this connection, 0 if not */
6167int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006168{
6169 if (!ssl_sock_is_ssl(conn))
6170 return 0;
6171
6172 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6173}
6174
6175/* returns result from SSL verify */
6176unsigned int ssl_sock_get_verify_result(struct connection *conn)
6177{
6178 if (!ssl_sock_is_ssl(conn))
6179 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6180
6181 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6182}
6183
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006184/* Returns the application layer protocol name in <str> and <len> when known.
6185 * Zero is returned if the protocol name was not found, otherwise non-zero is
6186 * returned. The string is allocated in the SSL context and doesn't have to be
6187 * freed by the caller. NPN is also checked if available since older versions
6188 * of openssl (1.0.1) which are more common in field only support this one.
6189 */
6190static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6191{
6192 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6193 return 0;
6194
6195 *str = NULL;
6196
6197#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6198 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6199 if (*str)
6200 return 1;
6201#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006202#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006203 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6204 if (*str)
6205 return 1;
6206#endif
6207 return 0;
6208}
6209
Willy Tarreau7875d092012-09-10 08:20:03 +02006210/***** Below are some sample fetching functions for ACL/patterns *****/
6211
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006212static int
6213smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6214{
6215 struct connection *conn;
6216
6217 conn = objt_conn(smp->sess->origin);
6218 if (!conn || conn->xprt != &ssl_sock)
6219 return 0;
6220
6221 smp->flags = 0;
6222 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006223 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6224 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006225
6226 return 1;
6227}
6228
Emeric Brune64aef12012-09-21 13:15:06 +02006229/* boolean, returns true if client cert was present */
6230static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006231smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006232{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006233 struct connection *conn;
6234
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006235 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006236 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006237 return 0;
6238
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006239 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006240 smp->flags |= SMP_F_MAY_CHANGE;
6241 return 0;
6242 }
6243
6244 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006245 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006246 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006247
6248 return 1;
6249}
6250
Emeric Brun43e79582014-10-29 19:03:26 +01006251/* binary, returns a certificate in a binary chunk (der/raw).
6252 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6253 * should be use.
6254 */
6255static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006256smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006257{
6258 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6259 X509 *crt = NULL;
6260 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006261 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006262 struct connection *conn;
6263
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006264 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006265 if (!conn || conn->xprt != &ssl_sock)
6266 return 0;
6267
6268 if (!(conn->flags & CO_FL_CONNECTED)) {
6269 smp->flags |= SMP_F_MAY_CHANGE;
6270 return 0;
6271 }
6272
6273 if (cert_peer)
6274 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6275 else
6276 crt = SSL_get_certificate(conn->xprt_ctx);
6277
6278 if (!crt)
6279 goto out;
6280
6281 smp_trash = get_trash_chunk();
6282 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6283 goto out;
6284
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006285 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006286 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006287 ret = 1;
6288out:
6289 /* SSL_get_peer_certificate, it increase X509 * ref count */
6290 if (cert_peer && crt)
6291 X509_free(crt);
6292 return ret;
6293}
6294
Emeric Brunba841a12014-04-30 17:05:08 +02006295/* binary, returns serial of certificate in a binary chunk.
6296 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6297 * should be use.
6298 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006299static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006300smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006301{
Emeric Brunba841a12014-04-30 17:05:08 +02006302 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006303 X509 *crt = NULL;
6304 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006305 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006306 struct connection *conn;
6307
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006308 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006309 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006310 return 0;
6311
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006312 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006313 smp->flags |= SMP_F_MAY_CHANGE;
6314 return 0;
6315 }
6316
Emeric Brunba841a12014-04-30 17:05:08 +02006317 if (cert_peer)
6318 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6319 else
6320 crt = SSL_get_certificate(conn->xprt_ctx);
6321
Willy Tarreau8d598402012-10-22 17:58:39 +02006322 if (!crt)
6323 goto out;
6324
Willy Tarreau47ca5452012-12-23 20:22:19 +01006325 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006326 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6327 goto out;
6328
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006329 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006330 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006331 ret = 1;
6332out:
Emeric Brunba841a12014-04-30 17:05:08 +02006333 /* SSL_get_peer_certificate, it increase X509 * ref count */
6334 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006335 X509_free(crt);
6336 return ret;
6337}
Emeric Brune64aef12012-09-21 13:15:06 +02006338
Emeric Brunba841a12014-04-30 17:05:08 +02006339/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6340 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6341 * should be use.
6342 */
James Votha051b4a2013-05-14 20:37:59 +02006343static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006344smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006345{
Emeric Brunba841a12014-04-30 17:05:08 +02006346 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006347 X509 *crt = NULL;
6348 const EVP_MD *digest;
6349 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006350 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006351 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006352
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006353 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006354 if (!conn || conn->xprt != &ssl_sock)
6355 return 0;
6356
6357 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006358 smp->flags |= SMP_F_MAY_CHANGE;
6359 return 0;
6360 }
6361
Emeric Brunba841a12014-04-30 17:05:08 +02006362 if (cert_peer)
6363 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6364 else
6365 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006366 if (!crt)
6367 goto out;
6368
6369 smp_trash = get_trash_chunk();
6370 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006371 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6372 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006373
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006374 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006375 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006376 ret = 1;
6377out:
Emeric Brunba841a12014-04-30 17:05:08 +02006378 /* SSL_get_peer_certificate, it increase X509 * ref count */
6379 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006380 X509_free(crt);
6381 return ret;
6382}
6383
Emeric Brunba841a12014-04-30 17:05:08 +02006384/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6385 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6386 * should be use.
6387 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006388static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006389smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006390{
Emeric Brunba841a12014-04-30 17:05:08 +02006391 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006392 X509 *crt = NULL;
6393 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006394 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006395 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006396
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006397 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006398 if (!conn || conn->xprt != &ssl_sock)
6399 return 0;
6400
6401 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006402 smp->flags |= SMP_F_MAY_CHANGE;
6403 return 0;
6404 }
6405
Emeric Brunba841a12014-04-30 17:05:08 +02006406 if (cert_peer)
6407 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6408 else
6409 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006410 if (!crt)
6411 goto out;
6412
Willy Tarreau47ca5452012-12-23 20:22:19 +01006413 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006414 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6415 goto out;
6416
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006417 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006418 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006419 ret = 1;
6420out:
Emeric Brunba841a12014-04-30 17:05:08 +02006421 /* SSL_get_peer_certificate, it increase X509 * ref count */
6422 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006423 X509_free(crt);
6424 return ret;
6425}
6426
Emeric Brunba841a12014-04-30 17:05:08 +02006427/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6428 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6429 * should be use.
6430 */
Emeric Brun87855892012-10-17 17:39:35 +02006431static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006432smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006433{
Emeric Brunba841a12014-04-30 17:05:08 +02006434 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006435 X509 *crt = NULL;
6436 X509_NAME *name;
6437 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006438 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006439 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006440
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006441 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006442 if (!conn || conn->xprt != &ssl_sock)
6443 return 0;
6444
6445 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006446 smp->flags |= SMP_F_MAY_CHANGE;
6447 return 0;
6448 }
6449
Emeric Brunba841a12014-04-30 17:05:08 +02006450 if (cert_peer)
6451 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6452 else
6453 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006454 if (!crt)
6455 goto out;
6456
6457 name = X509_get_issuer_name(crt);
6458 if (!name)
6459 goto out;
6460
Willy Tarreau47ca5452012-12-23 20:22:19 +01006461 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006462 if (args && args[0].type == ARGT_STR) {
6463 int pos = 1;
6464
6465 if (args[1].type == ARGT_SINT)
6466 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006467
6468 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6469 goto out;
6470 }
6471 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6472 goto out;
6473
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006474 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006475 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006476 ret = 1;
6477out:
Emeric Brunba841a12014-04-30 17:05:08 +02006478 /* SSL_get_peer_certificate, it increase X509 * ref count */
6479 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006480 X509_free(crt);
6481 return ret;
6482}
6483
Emeric Brunba841a12014-04-30 17:05:08 +02006484/* string, returns notbefore date in ASN1_UTCTIME format.
6485 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6486 * should be use.
6487 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006488static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006489smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006490{
Emeric Brunba841a12014-04-30 17:05:08 +02006491 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006492 X509 *crt = NULL;
6493 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006494 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006495 struct connection *conn;
6496
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006497 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006498 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006499 return 0;
6500
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006501 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006502 smp->flags |= SMP_F_MAY_CHANGE;
6503 return 0;
6504 }
6505
Emeric Brunba841a12014-04-30 17:05:08 +02006506 if (cert_peer)
6507 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6508 else
6509 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006510 if (!crt)
6511 goto out;
6512
Willy Tarreau47ca5452012-12-23 20:22:19 +01006513 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006514 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6515 goto out;
6516
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006517 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006518 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006519 ret = 1;
6520out:
Emeric Brunba841a12014-04-30 17:05:08 +02006521 /* SSL_get_peer_certificate, it increase X509 * ref count */
6522 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006523 X509_free(crt);
6524 return ret;
6525}
6526
Emeric Brunba841a12014-04-30 17:05:08 +02006527/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6528 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6529 * should be use.
6530 */
Emeric Brun87855892012-10-17 17:39:35 +02006531static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006532smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006533{
Emeric Brunba841a12014-04-30 17:05:08 +02006534 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006535 X509 *crt = NULL;
6536 X509_NAME *name;
6537 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006538 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006539 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006540
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006541 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006542 if (!conn || conn->xprt != &ssl_sock)
6543 return 0;
6544
6545 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006546 smp->flags |= SMP_F_MAY_CHANGE;
6547 return 0;
6548 }
6549
Emeric Brunba841a12014-04-30 17:05:08 +02006550 if (cert_peer)
6551 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6552 else
6553 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006554 if (!crt)
6555 goto out;
6556
6557 name = X509_get_subject_name(crt);
6558 if (!name)
6559 goto out;
6560
Willy Tarreau47ca5452012-12-23 20:22:19 +01006561 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006562 if (args && args[0].type == ARGT_STR) {
6563 int pos = 1;
6564
6565 if (args[1].type == ARGT_SINT)
6566 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006567
6568 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6569 goto out;
6570 }
6571 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6572 goto out;
6573
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006574 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006575 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006576 ret = 1;
6577out:
Emeric Brunba841a12014-04-30 17:05:08 +02006578 /* SSL_get_peer_certificate, it increase X509 * ref count */
6579 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006580 X509_free(crt);
6581 return ret;
6582}
Emeric Brun9143d372012-12-20 15:44:16 +01006583
6584/* integer, returns true if current session use a client certificate */
6585static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006586smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006587{
6588 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006589 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006590
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006591 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006592 if (!conn || conn->xprt != &ssl_sock)
6593 return 0;
6594
6595 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006596 smp->flags |= SMP_F_MAY_CHANGE;
6597 return 0;
6598 }
6599
6600 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006601 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006602 if (crt) {
6603 X509_free(crt);
6604 }
6605
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006606 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006607 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006608 return 1;
6609}
6610
Emeric Brunba841a12014-04-30 17:05:08 +02006611/* integer, returns the certificate version
6612 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6613 * should be use.
6614 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006615static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006616smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006617{
Emeric Brunba841a12014-04-30 17:05:08 +02006618 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006619 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006620 struct connection *conn;
6621
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006622 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006623 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006624 return 0;
6625
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006626 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006627 smp->flags |= SMP_F_MAY_CHANGE;
6628 return 0;
6629 }
6630
Emeric Brunba841a12014-04-30 17:05:08 +02006631 if (cert_peer)
6632 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6633 else
6634 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006635 if (!crt)
6636 return 0;
6637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006638 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006639 /* SSL_get_peer_certificate increase X509 * ref count */
6640 if (cert_peer)
6641 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006642 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006643
6644 return 1;
6645}
6646
Emeric Brunba841a12014-04-30 17:05:08 +02006647/* string, returns the certificate's signature algorithm.
6648 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6649 * should be use.
6650 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006651static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006652smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006653{
Emeric Brunba841a12014-04-30 17:05:08 +02006654 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006655 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006656 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006657 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006658 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006659
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006660 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006661 if (!conn || conn->xprt != &ssl_sock)
6662 return 0;
6663
6664 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006665 smp->flags |= SMP_F_MAY_CHANGE;
6666 return 0;
6667 }
6668
Emeric Brunba841a12014-04-30 17:05:08 +02006669 if (cert_peer)
6670 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6671 else
6672 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006673 if (!crt)
6674 return 0;
6675
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006676 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6677 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006678
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006679 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6680 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006681 /* SSL_get_peer_certificate increase X509 * ref count */
6682 if (cert_peer)
6683 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006684 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006685 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006686
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006687 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006688 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006689 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006690 /* SSL_get_peer_certificate increase X509 * ref count */
6691 if (cert_peer)
6692 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006693
6694 return 1;
6695}
6696
Emeric Brunba841a12014-04-30 17:05:08 +02006697/* string, returns the certificate's key algorithm.
6698 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6699 * should be use.
6700 */
Emeric Brun521a0112012-10-22 12:22:55 +02006701static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006702smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006703{
Emeric Brunba841a12014-04-30 17:05:08 +02006704 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006705 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006706 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006707 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006708 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006709
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006710 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006711 if (!conn || conn->xprt != &ssl_sock)
6712 return 0;
6713
6714 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006715 smp->flags |= SMP_F_MAY_CHANGE;
6716 return 0;
6717 }
6718
Emeric Brunba841a12014-04-30 17:05:08 +02006719 if (cert_peer)
6720 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6721 else
6722 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006723 if (!crt)
6724 return 0;
6725
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006726 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6727 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006728
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006729 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6730 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006731 /* SSL_get_peer_certificate increase X509 * ref count */
6732 if (cert_peer)
6733 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006734 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006735 }
Emeric Brun521a0112012-10-22 12:22:55 +02006736
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006737 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006738 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006739 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006740 if (cert_peer)
6741 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006742
6743 return 1;
6744}
6745
Emeric Brun645ae792014-04-30 14:21:06 +02006746/* boolean, returns true if front conn. transport layer is SSL.
6747 * This function is also usable on backend conn if the fetch keyword 5th
6748 * char is 'b'.
6749 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006750static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006751smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006752{
Emeric Bruneb8def92018-02-19 15:59:48 +01006753 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6754 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006755
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006756 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006757 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006758 return 1;
6759}
6760
Emeric Brun2525b6b2012-10-18 15:59:43 +02006761/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006762static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006763smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006764{
6765#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006766 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006767
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006768 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006769 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006770 conn->xprt_ctx &&
6771 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006772 return 1;
6773#else
6774 return 0;
6775#endif
6776}
6777
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006778/* boolean, returns true if client session has been resumed.
6779 * This function is also usable on backend conn if the fetch keyword 5th
6780 * char is 'b'.
6781 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006782static int
6783smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6784{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006785 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6786 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6787
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006788
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006789 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006790 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006791 conn->xprt_ctx &&
6792 SSL_session_reused(conn->xprt_ctx);
6793 return 1;
6794}
6795
Emeric Brun645ae792014-04-30 14:21:06 +02006796/* string, returns the used cipher if front conn. transport layer is SSL.
6797 * This function is also usable on backend conn if the fetch keyword 5th
6798 * char is 'b'.
6799 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006800static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006801smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006802{
Emeric Bruneb8def92018-02-19 15:59:48 +01006803 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6804 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006805
Willy Tarreaube508f12016-03-10 11:47:01 +01006806 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006807 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006808 return 0;
6809
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006810 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6811 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006812 return 0;
6813
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006814 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006815 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006816 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006817
6818 return 1;
6819}
6820
Emeric Brun645ae792014-04-30 14:21:06 +02006821/* integer, returns the algoritm's keysize if front conn. transport layer
6822 * is SSL.
6823 * This function is also usable on backend conn if the fetch keyword 5th
6824 * char is 'b'.
6825 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006826static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006827smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006828{
Emeric Bruneb8def92018-02-19 15:59:48 +01006829 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6830 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006831 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006832
Emeric Brun589fcad2012-10-16 14:13:26 +02006833 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006834 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006835 return 0;
6836
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006837 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006838 return 0;
6839
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006840 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006841 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006842
6843 return 1;
6844}
6845
Emeric Brun645ae792014-04-30 14:21:06 +02006846/* integer, returns the used keysize if front conn. transport layer is SSL.
6847 * This function is also usable on backend conn if the fetch keyword 5th
6848 * char is 'b'.
6849 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006850static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006851smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006852{
Emeric Bruneb8def92018-02-19 15:59:48 +01006853 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6854 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006855
Emeric Brun589fcad2012-10-16 14:13:26 +02006856 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006857 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6858 return 0;
6859
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006860 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6861 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006862 return 0;
6863
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006864 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006865
6866 return 1;
6867}
6868
Bernard Spil13c53f82018-02-15 13:34:58 +01006869#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006870static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006871smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006872{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006873 struct connection *conn;
6874
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006875 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006876 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006877
Olivier Houchard6b77f492018-11-22 18:18:29 +01006878 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6879 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006880 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6881 return 0;
6882
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006883 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006884 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006885 (const unsigned char **)&smp->data.u.str.area,
6886 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006887
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006888 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006889 return 0;
6890
6891 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006892}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006893#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006894
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006895#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006896static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006897smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006898{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899 struct connection *conn;
6900
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006901 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006902 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006903
Olivier Houchard6b77f492018-11-22 18:18:29 +01006904 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6905 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6906
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006907 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006908 return 0;
6909
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006910 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006911 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006912 (const unsigned char **)&smp->data.u.str.area,
6913 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006914
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006915 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006916 return 0;
6917
6918 return 1;
6919}
6920#endif
6921
Emeric Brun645ae792014-04-30 14:21:06 +02006922/* string, returns the used protocol if front conn. transport layer is SSL.
6923 * This function is also usable on backend conn if the fetch keyword 5th
6924 * char is 'b'.
6925 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006926static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006927smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006928{
Emeric Bruneb8def92018-02-19 15:59:48 +01006929 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6930 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006931
Emeric Brun589fcad2012-10-16 14:13:26 +02006932 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006933 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6934 return 0;
6935
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006936 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6937 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006938 return 0;
6939
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006940 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006941 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006942 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006943
6944 return 1;
6945}
6946
Willy Tarreau87b09662015-04-03 00:22:06 +02006947/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006948 * This function is also usable on backend conn if the fetch keyword 5th
6949 * char is 'b'.
6950 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006951#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006952static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006953smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006954{
Emeric Bruneb8def92018-02-19 15:59:48 +01006955 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6956 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006957 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006958
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006959 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006960 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006961
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006962 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6963 return 0;
6964
Willy Tarreau192252e2015-04-04 01:47:55 +02006965 ssl_sess = SSL_get_session(conn->xprt_ctx);
6966 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006967 return 0;
6968
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006969 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6970 (unsigned int *)&smp->data.u.str.data);
6971 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006972 return 0;
6973
6974 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006975}
Patrick Hemmer41966772018-04-28 19:15:48 -04006976#endif
6977
Emeric Brunfe68f682012-10-16 14:59:28 +02006978
Patrick Hemmere0275472018-04-28 19:15:51 -04006979#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6980static int
6981smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6982{
6983 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6984 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6985 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006986 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006987
6988 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6989 return 0;
6990
6991 ssl_sess = SSL_get_session(conn->xprt_ctx);
6992 if (!ssl_sess)
6993 return 0;
6994
6995 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006996 data->data = SSL_SESSION_get_master_key(ssl_sess,
6997 (unsigned char *) data->area,
6998 data->size);
6999 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007000 return 0;
7001
7002 smp->flags = 0;
7003 smp->data.type = SMP_T_BIN;
7004 smp->data.u.str = *data;
7005
7006 return 1;
7007}
7008#endif
7009
Patrick Hemmer41966772018-04-28 19:15:48 -04007010#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007011static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007012smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007013{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007014 struct connection *conn;
7015
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007016 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007017 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007018
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007019 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007020 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7021 return 0;
7022
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007023 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7024 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007025 return 0;
7026
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007027 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007028 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007029}
Patrick Hemmer41966772018-04-28 19:15:48 -04007030#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007031
David Sc1ad52e2014-04-08 18:48:47 -04007032static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007033smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7034{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007035 struct connection *conn;
7036 struct ssl_capture *capture;
7037
7038 conn = objt_conn(smp->sess->origin);
7039 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7040 return 0;
7041
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007042 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007043 if (!capture)
7044 return 0;
7045
7046 smp->flags = SMP_F_CONST;
7047 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007048 smp->data.u.str.area = capture->ciphersuite;
7049 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007050 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007051}
7052
7053static int
7054smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7055{
Willy Tarreau83061a82018-07-13 11:56:34 +02007056 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007057
7058 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7059 return 0;
7060
7061 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007062 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007063 smp->data.type = SMP_T_BIN;
7064 smp->data.u.str = *data;
7065 return 1;
7066}
7067
7068static int
7069smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7070{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007071 struct connection *conn;
7072 struct ssl_capture *capture;
7073
7074 conn = objt_conn(smp->sess->origin);
7075 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7076 return 0;
7077
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007078 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007079 if (!capture)
7080 return 0;
7081
7082 smp->data.type = SMP_T_SINT;
7083 smp->data.u.sint = capture->xxh64;
7084 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007085}
7086
7087static int
7088smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7089{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007090#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007091 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007092 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007093
7094 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7095 return 0;
7096
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007097 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007098 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007099 const char *str;
7100 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007101 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007102 uint16_t id = (bin[0] << 8) | bin[1];
7103#if defined(OPENSSL_IS_BORINGSSL)
7104 cipher = SSL_get_cipher_by_value(id);
7105#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007106 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007107 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7108#endif
7109 str = SSL_CIPHER_get_name(cipher);
7110 if (!str || strcmp(str, "(NONE)") == 0)
7111 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007112 else
7113 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7114 }
7115 smp->data.type = SMP_T_STR;
7116 smp->data.u.str = *data;
7117 return 1;
7118#else
7119 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7120#endif
7121}
7122
Patrick Hemmer41966772018-04-28 19:15:48 -04007123#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007124static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007125smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007126{
Emeric Bruneb8def92018-02-19 15:59:48 +01007127 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7128 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007129 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007130 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007131
7132 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007133 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7134 return 0;
7135
7136 if (!(conn->flags & CO_FL_CONNECTED)) {
7137 smp->flags |= SMP_F_MAY_CHANGE;
7138 return 0;
7139 }
7140
7141 finished_trash = get_trash_chunk();
7142 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007143 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7144 finished_trash->area,
7145 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007146 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007147 finished_len = SSL_get_finished(conn->xprt_ctx,
7148 finished_trash->area,
7149 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007150
7151 if (!finished_len)
7152 return 0;
7153
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007154 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007155 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007156 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007157
7158 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007159}
Patrick Hemmer41966772018-04-28 19:15:48 -04007160#endif
David Sc1ad52e2014-04-08 18:48:47 -04007161
Emeric Brun2525b6b2012-10-18 15:59:43 +02007162/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007163static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007164smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007165{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007166 struct connection *conn;
7167
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007168 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007169 if (!conn || conn->xprt != &ssl_sock)
7170 return 0;
7171
7172 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007173 smp->flags = SMP_F_MAY_CHANGE;
7174 return 0;
7175 }
7176
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007177 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007178 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007179 smp->flags = 0;
7180
7181 return 1;
7182}
7183
Emeric Brun2525b6b2012-10-18 15:59:43 +02007184/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007185static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007186smp_fetch_ssl_c_ca_err_depth(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007187{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007188 struct connection *conn;
7189
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007190 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007191 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007192 return 0;
7193
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007194 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007195 smp->flags = SMP_F_MAY_CHANGE;
7196 return 0;
7197 }
7198
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007199 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007200 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007201 smp->flags = 0;
7202
7203 return 1;
7204}
7205
Emeric Brun2525b6b2012-10-18 15:59:43 +02007206/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007207static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007208smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007209{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210 struct connection *conn;
7211
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007212 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007213 if (!conn || conn->xprt != &ssl_sock)
7214 return 0;
7215
7216 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007217 smp->flags = SMP_F_MAY_CHANGE;
7218 return 0;
7219 }
7220
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007221 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007222 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007223 smp->flags = 0;
7224
7225 return 1;
7226}
7227
Emeric Brun2525b6b2012-10-18 15:59:43 +02007228/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007229static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007230smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007231{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007232 struct connection *conn;
7233
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007234 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007235 if (!conn || conn->xprt != &ssl_sock)
7236 return 0;
7237
7238 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007239 smp->flags = SMP_F_MAY_CHANGE;
7240 return 0;
7241 }
7242
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007243 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007244 return 0;
7245
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007246 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007247 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007248 smp->flags = 0;
7249
7250 return 1;
7251}
7252
Emeric Brunfb510ea2012-10-05 12:00:26 +02007253/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007254static int ssl_bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02007255{
7256 if (!*args[cur_arg + 1]) {
7257 if (err)
7258 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7259 return ERR_ALERT | ERR_FATAL;
7260 }
7261
Willy Tarreauef934602016-12-22 23:12:01 +01007262 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7263 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007264 else
7265 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007266
Emeric Brund94b3fe2012-09-20 18:23:56 +02007267 return 0;
7268}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007269static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7270{
7271 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7272}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007273
Christopher Faulet31af49d2015-06-09 17:29:50 +02007274/* parse the "ca-sign-file" bind keyword */
7275static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7276{
7277 if (!*args[cur_arg + 1]) {
7278 if (err)
7279 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7280 return ERR_ALERT | ERR_FATAL;
7281 }
7282
Willy Tarreauef934602016-12-22 23:12:01 +01007283 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7284 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007285 else
7286 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7287
7288 return 0;
7289}
7290
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007291/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007292static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7293{
7294 if (!*args[cur_arg + 1]) {
7295 if (err)
7296 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7297 return ERR_ALERT | ERR_FATAL;
7298 }
7299 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7300 return 0;
7301}
7302
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007303/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007304static int ssl_bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007305{
7306 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007307 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007308 return ERR_ALERT | ERR_FATAL;
7309 }
7310
Emeric Brun76d88952012-10-05 15:47:31 +02007311 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007312 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007313 return 0;
7314}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007315static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7316{
7317 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7318}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007319
7320#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7321/* parse the "ciphersuites" bind keyword */
7322static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7323{
7324 if (!*args[cur_arg + 1]) {
7325 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7326 return ERR_ALERT | ERR_FATAL;
7327 }
7328
7329 free(conf->ciphersuites);
7330 conf->ciphersuites = strdup(args[cur_arg + 1]);
7331 return 0;
7332}
7333static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7334{
7335 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7336}
7337#endif
7338
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007339/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007340static int bind_parse_crt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007341{
Willy Tarreau38011032013-08-13 16:59:39 +02007342 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007343
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007344 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007345 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007346 return ERR_ALERT | ERR_FATAL;
7347 }
7348
Willy Tarreauef934602016-12-22 23:12:01 +01007349 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7350 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007351 memprintf(err, "'%s' : path too long", args[cur_arg]);
7352 return ERR_ALERT | ERR_FATAL;
7353 }
Willy Tarreauef934602016-12-22 23:12:01 +01007354 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007355 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007356 return ERR_ALERT | ERR_FATAL;
7357
7358 return 0;
7359 }
7360
Willy Tarreau03209342016-12-22 17:08:28 +01007361 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007362 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007363
7364 return 0;
7365}
7366
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007367/* parse the "crt-list" bind keyword */
7368static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7369{
7370 if (!*args[cur_arg + 1]) {
7371 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7372 return ERR_ALERT | ERR_FATAL;
7373 }
7374
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007375 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007376 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007377 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007378 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007379
7380 return 0;
7381}
7382
Emeric Brunfb510ea2012-10-05 12:00:26 +02007383/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007384static int ssl_bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02007385{
Emeric Brun051cdab2012-10-02 19:25:50 +02007386#ifndef X509_V_FLAG_CRL_CHECK
7387 if (err)
7388 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7389 return ERR_ALERT | ERR_FATAL;
7390#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007391 if (!*args[cur_arg + 1]) {
7392 if (err)
7393 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7394 return ERR_ALERT | ERR_FATAL;
7395 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007396
Willy Tarreauef934602016-12-22 23:12:01 +01007397 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7398 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007399 else
7400 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007401
Emeric Brun2b58d042012-09-20 17:10:03 +02007402 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007403#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007404}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007405static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7406{
7407 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7408}
Emeric Brun2b58d042012-09-20 17:10:03 +02007409
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007410/* parse the "curves" bind keyword keyword */
7411static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7412{
7413#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7414 if (!*args[cur_arg + 1]) {
7415 if (err)
7416 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7417 return ERR_ALERT | ERR_FATAL;
7418 }
7419 conf->curves = strdup(args[cur_arg + 1]);
7420 return 0;
7421#else
7422 if (err)
7423 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7424 return ERR_ALERT | ERR_FATAL;
7425#endif
7426}
7427static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7428{
7429 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7430}
7431
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007432/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007433static int ssl_bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brun2b58d042012-09-20 17:10:03 +02007434{
7435#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7436 if (err)
7437 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7438 return ERR_ALERT | ERR_FATAL;
7439#elif defined(OPENSSL_NO_ECDH)
7440 if (err)
7441 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7442 return ERR_ALERT | ERR_FATAL;
7443#else
7444 if (!*args[cur_arg + 1]) {
7445 if (err)
7446 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7447 return ERR_ALERT | ERR_FATAL;
7448 }
7449
7450 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007451
7452 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007453#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007454}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007455static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7456{
7457 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7458}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007459
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007460/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007461static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7462{
7463 int code;
7464 char *p = args[cur_arg + 1];
7465 unsigned long long *ignerr = &conf->crt_ignerr;
7466
7467 if (!*p) {
7468 if (err)
7469 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7470 return ERR_ALERT | ERR_FATAL;
7471 }
7472
7473 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7474 ignerr = &conf->ca_ignerr;
7475
7476 if (strcmp(p, "all") == 0) {
7477 *ignerr = ~0ULL;
7478 return 0;
7479 }
7480
7481 while (p) {
7482 code = atoi(p);
7483 if ((code <= 0) || (code > 63)) {
7484 if (err)
7485 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7486 args[cur_arg], code, args[cur_arg + 1]);
7487 return ERR_ALERT | ERR_FATAL;
7488 }
7489 *ignerr |= 1ULL << code;
7490 p = strchr(p, ',');
7491 if (p)
7492 p++;
7493 }
7494
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007495 return 0;
7496}
7497
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007498/* parse tls_method_options "no-xxx" and "force-xxx" */
7499static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007500{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007501 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007502 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007503 p = strchr(arg, '-');
7504 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007505 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007506 p++;
7507 if (!strcmp(p, "sslv3"))
7508 v = CONF_SSLV3;
7509 else if (!strcmp(p, "tlsv10"))
7510 v = CONF_TLSV10;
7511 else if (!strcmp(p, "tlsv11"))
7512 v = CONF_TLSV11;
7513 else if (!strcmp(p, "tlsv12"))
7514 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007515 else if (!strcmp(p, "tlsv13"))
7516 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007517 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007518 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007519 if (!strncmp(arg, "no-", 3))
7520 methods->flags |= methodVersions[v].flag;
7521 else if (!strncmp(arg, "force-", 6))
7522 methods->min = methods->max = v;
7523 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007524 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007525 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007526 fail:
7527 if (err)
7528 memprintf(err, "'%s' : option not implemented", arg);
7529 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007530}
7531
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007532static int bind_parse_tls_method_options(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007533{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007534 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007535}
7536
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007537static int srv_parse_tls_method_options(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007538{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007539 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7540}
7541
7542/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7543static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7544{
7545 uint16_t i, v = 0;
7546 char *argv = args[cur_arg + 1];
7547 if (!*argv) {
7548 if (err)
7549 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7550 return ERR_ALERT | ERR_FATAL;
7551 }
7552 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7553 if (!strcmp(argv, methodVersions[i].name))
7554 v = i;
7555 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007556 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007557 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007558 return ERR_ALERT | ERR_FATAL;
7559 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007560 if (!strcmp("ssl-min-ver", args[cur_arg]))
7561 methods->min = v;
7562 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7563 methods->max = v;
7564 else {
7565 if (err)
7566 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7567 return ERR_ALERT | ERR_FATAL;
7568 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007569 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007570}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007571
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007572static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7573{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007574#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007575 ha_warning("crt-list: ssl-min-ver and ssl-max-ver are not supported with this Openssl version (skipped).\n");
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007576#endif
7577 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7578}
7579
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007580static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7581{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007582 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007583}
7584
7585static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7586{
7587 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7588}
7589
Emeric Brun2d0c4822012-10-02 13:45:20 +02007590/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007591static int bind_parse_no_tls_tickets(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Emeric Brun2d0c4822012-10-02 13:45:20 +02007592{
Emeric Brun89675492012-10-05 13:48:26 +02007593 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007594 return 0;
7595}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007596
Olivier Houchardc2aae742017-09-22 18:26:28 +02007597/* parse the "allow-0rtt" bind keyword */
7598static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7599{
7600 conf->early_data = 1;
7601 return 0;
7602}
7603
7604static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7605{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007606 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007607 return 0;
7608}
7609
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007610/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007611static int ssl_bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007612{
Bernard Spil13c53f82018-02-15 13:34:58 +01007613#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007614 char *p1, *p2;
7615
7616 if (!*args[cur_arg + 1]) {
7617 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7618 return ERR_ALERT | ERR_FATAL;
7619 }
7620
7621 free(conf->npn_str);
7622
Willy Tarreau3724da12016-02-12 17:11:12 +01007623 /* the NPN string is built as a suite of (<len> <name>)*,
7624 * so we reuse each comma to store the next <len> and need
7625 * one more for the end of the string.
7626 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007627 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007628 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007629 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7630
7631 /* replace commas with the name length */
7632 p1 = conf->npn_str;
7633 p2 = p1 + 1;
7634 while (1) {
7635 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7636 if (!p2)
7637 p2 = p1 + 1 + strlen(p1 + 1);
7638
7639 if (p2 - (p1 + 1) > 255) {
7640 *p2 = '\0';
7641 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7642 return ERR_ALERT | ERR_FATAL;
7643 }
7644
7645 *p1 = p2 - (p1 + 1);
7646 p1 = p2;
7647
7648 if (!*p2)
7649 break;
7650
7651 *(p2++) = '\0';
7652 }
7653 return 0;
7654#else
7655 if (err)
7656 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7657 return ERR_ALERT | ERR_FATAL;
7658#endif
7659}
7660
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007661static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7662{
7663 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7664}
7665
Willy Tarreauab861d32013-04-02 02:30:41 +02007666/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007667static int ssl_bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Willy Tarreauab861d32013-04-02 02:30:41 +02007668{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007669#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007670 char *p1, *p2;
7671
7672 if (!*args[cur_arg + 1]) {
7673 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7674 return ERR_ALERT | ERR_FATAL;
7675 }
7676
7677 free(conf->alpn_str);
7678
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007679 /* the ALPN string is built as a suite of (<len> <name>)*,
7680 * so we reuse each comma to store the next <len> and need
7681 * one more for the end of the string.
7682 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007683 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007684 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007685 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7686
7687 /* replace commas with the name length */
7688 p1 = conf->alpn_str;
7689 p2 = p1 + 1;
7690 while (1) {
7691 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7692 if (!p2)
7693 p2 = p1 + 1 + strlen(p1 + 1);
7694
7695 if (p2 - (p1 + 1) > 255) {
7696 *p2 = '\0';
7697 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7698 return ERR_ALERT | ERR_FATAL;
7699 }
7700
7701 *p1 = p2 - (p1 + 1);
7702 p1 = p2;
7703
7704 if (!*p2)
7705 break;
7706
7707 *(p2++) = '\0';
7708 }
7709 return 0;
7710#else
7711 if (err)
7712 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7713 return ERR_ALERT | ERR_FATAL;
7714#endif
7715}
7716
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007717static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7718{
7719 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7720}
7721
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007722/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007723static int bind_parse_ssl(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007724{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007725 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007726 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007727
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007728 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7729 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007730#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7731 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7732 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7733#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007734 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007735 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7736 if (!conf->ssl_conf.ssl_methods.min)
7737 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7738 if (!conf->ssl_conf.ssl_methods.max)
7739 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007740
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007741 return 0;
7742}
7743
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007744/* parse the "prefer-client-ciphers" bind keyword */
7745static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7746{
7747 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7748 return 0;
7749}
7750
Christopher Faulet31af49d2015-06-09 17:29:50 +02007751/* parse the "generate-certificates" bind keyword */
7752static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7753{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007754#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007755 conf->generate_certs = 1;
7756#else
7757 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7758 err && *err ? *err : "");
7759#endif
7760 return 0;
7761}
7762
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007763/* parse the "strict-sni" bind keyword */
7764static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7765{
7766 conf->strict_sni = 1;
7767 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007768}
7769
7770/* parse the "tls-ticket-keys" bind keyword */
7771static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7772{
7773#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7774 FILE *f;
7775 int i = 0;
7776 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007777 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007778
7779 if (!*args[cur_arg + 1]) {
7780 if (err)
7781 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7782 return ERR_ALERT | ERR_FATAL;
7783 }
7784
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007785 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007786 if (keys_ref) {
7787 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007788 conf->keys_ref = keys_ref;
7789 return 0;
7790 }
7791
Vincent Bernat02779b62016-04-03 13:48:43 +02007792 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007793 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007794
7795 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7796 if (err)
7797 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7798 return ERR_ALERT | ERR_FATAL;
7799 }
7800
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007801 keys_ref->filename = strdup(args[cur_arg + 1]);
7802
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007803 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7804 int len = strlen(thisline);
7805 /* Strip newline characters from the end */
7806 if(thisline[len - 1] == '\n')
7807 thisline[--len] = 0;
7808
7809 if(thisline[len - 1] == '\r')
7810 thisline[--len] = 0;
7811
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007812 if (base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(struct tls_sess_key)) != sizeof(struct tls_sess_key)) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007813 if (err)
7814 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007815 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007816 return ERR_ALERT | ERR_FATAL;
7817 }
7818 i++;
7819 }
7820
7821 if (i < TLS_TICKETS_NO) {
7822 if (err)
7823 memprintf(err, "'%s' : please supply at least %d keys in the tls-tickets-file", args[cur_arg+1], TLS_TICKETS_NO);
mildis16aa0152016-06-22 17:46:29 +02007824 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007825 return ERR_ALERT | ERR_FATAL;
7826 }
7827
7828 fclose(f);
7829
7830 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007831 i -= 2;
7832 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007833 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007834 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007835 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007836 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007837
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007838 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7839
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007840 return 0;
7841#else
7842 if (err)
7843 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7844 return ERR_ALERT | ERR_FATAL;
7845#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007846}
7847
Emeric Brund94b3fe2012-09-20 18:23:56 +02007848/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007849static int ssl_bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
Emeric Brund94b3fe2012-09-20 18:23:56 +02007850{
7851 if (!*args[cur_arg + 1]) {
7852 if (err)
7853 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7854 return ERR_ALERT | ERR_FATAL;
7855 }
7856
7857 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007858 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007859 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007860 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007861 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007862 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007863 else {
7864 if (err)
7865 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7866 args[cur_arg], args[cur_arg + 1]);
7867 return ERR_ALERT | ERR_FATAL;
7868 }
7869
7870 return 0;
7871}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007872static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7873{
7874 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7875}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007876
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007877/* parse the "no-ca-names" bind keyword */
7878static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7879{
7880 conf->no_ca_names = 1;
7881 return 0;
7882}
7883static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7884{
7885 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7886}
7887
Willy Tarreau92faadf2012-10-10 23:04:25 +02007888/************** "server" keywords ****************/
7889
Olivier Houchardc7566002018-11-20 23:33:50 +01007890/* parse the "npn" bind keyword */
7891static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7892{
7893#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7894 char *p1, *p2;
7895
7896 if (!*args[*cur_arg + 1]) {
7897 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7898 return ERR_ALERT | ERR_FATAL;
7899 }
7900
7901 free(newsrv->ssl_ctx.npn_str);
7902
7903 /* the NPN string is built as a suite of (<len> <name>)*,
7904 * so we reuse each comma to store the next <len> and need
7905 * one more for the end of the string.
7906 */
7907 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7908 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7909 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7910 newsrv->ssl_ctx.npn_len);
7911
7912 /* replace commas with the name length */
7913 p1 = newsrv->ssl_ctx.npn_str;
7914 p2 = p1 + 1;
7915 while (1) {
7916 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7917 newsrv->ssl_ctx.npn_len - (p1 + 1));
7918 if (!p2)
7919 p2 = p1 + 1 + strlen(p1 + 1);
7920
7921 if (p2 - (p1 + 1) > 255) {
7922 *p2 = '\0';
7923 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7924 return ERR_ALERT | ERR_FATAL;
7925 }
7926
7927 *p1 = p2 - (p1 + 1);
7928 p1 = p2;
7929
7930 if (!*p2)
7931 break;
7932
7933 *(p2++) = '\0';
7934 }
7935 return 0;
7936#else
7937 if (err)
7938 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7939 return ERR_ALERT | ERR_FATAL;
7940#endif
7941}
7942
7943/* parse the "alpn" bind keyword */
7944static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7945{
7946#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7947 char *p1, *p2;
7948
7949 if (!*args[*cur_arg + 1]) {
7950 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7951 return ERR_ALERT | ERR_FATAL;
7952 }
7953
7954 free(newsrv->ssl_ctx.alpn_str);
7955
7956 /* the ALPN string is built as a suite of (<len> <name>)*,
7957 * so we reuse each comma to store the next <len> and need
7958 * one more for the end of the string.
7959 */
7960 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7961 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7962 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7963 newsrv->ssl_ctx.alpn_len);
7964
7965 /* replace commas with the name length */
7966 p1 = newsrv->ssl_ctx.alpn_str;
7967 p2 = p1 + 1;
7968 while (1) {
7969 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7970 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7971 if (!p2)
7972 p2 = p1 + 1 + strlen(p1 + 1);
7973
7974 if (p2 - (p1 + 1) > 255) {
7975 *p2 = '\0';
7976 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7977 return ERR_ALERT | ERR_FATAL;
7978 }
7979
7980 *p1 = p2 - (p1 + 1);
7981 p1 = p2;
7982
7983 if (!*p2)
7984 break;
7985
7986 *(p2++) = '\0';
7987 }
7988 return 0;
7989#else
7990 if (err)
7991 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
7992 return ERR_ALERT | ERR_FATAL;
7993#endif
7994}
7995
Emeric Brunef42d922012-10-11 16:11:36 +02007996/* parse the "ca-file" server keyword */
7997static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7998{
7999 if (!*args[*cur_arg + 1]) {
8000 if (err)
8001 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8002 return ERR_ALERT | ERR_FATAL;
8003 }
8004
Willy Tarreauef934602016-12-22 23:12:01 +01008005 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8006 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008007 else
8008 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8009
8010 return 0;
8011}
8012
Olivier Houchard9130a962017-10-17 17:33:43 +02008013/* parse the "check-sni" server keyword */
8014static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8015{
8016 if (!*args[*cur_arg + 1]) {
8017 if (err)
8018 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8019 return ERR_ALERT | ERR_FATAL;
8020 }
8021
8022 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8023 if (!newsrv->check.sni) {
8024 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8025 return ERR_ALERT | ERR_FATAL;
8026 }
8027 return 0;
8028
8029}
8030
Willy Tarreau92faadf2012-10-10 23:04:25 +02008031/* parse the "check-ssl" server keyword */
8032static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8033{
8034 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008035 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8036 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008037#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8038 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8039 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8040#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008041 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008042 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8043 if (!newsrv->ssl_ctx.methods.min)
8044 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8045 if (!newsrv->ssl_ctx.methods.max)
8046 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8047
Willy Tarreau92faadf2012-10-10 23:04:25 +02008048 return 0;
8049}
8050
8051/* parse the "ciphers" server keyword */
8052static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8053{
8054 if (!*args[*cur_arg + 1]) {
8055 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8056 return ERR_ALERT | ERR_FATAL;
8057 }
8058
8059 free(newsrv->ssl_ctx.ciphers);
8060 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8061 return 0;
8062}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008063
8064#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8065/* parse the "ciphersuites" server keyword */
8066static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8067{
8068 if (!*args[*cur_arg + 1]) {
8069 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8070 return ERR_ALERT | ERR_FATAL;
8071 }
8072
8073 free(newsrv->ssl_ctx.ciphersuites);
8074 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8075 return 0;
8076}
8077#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008078
Emeric Brunef42d922012-10-11 16:11:36 +02008079/* parse the "crl-file" server keyword */
8080static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8081{
8082#ifndef X509_V_FLAG_CRL_CHECK
8083 if (err)
8084 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8085 return ERR_ALERT | ERR_FATAL;
8086#else
8087 if (!*args[*cur_arg + 1]) {
8088 if (err)
8089 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8090 return ERR_ALERT | ERR_FATAL;
8091 }
8092
Willy Tarreauef934602016-12-22 23:12:01 +01008093 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8094 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008095 else
8096 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8097
8098 return 0;
8099#endif
8100}
8101
Emeric Bruna7aa3092012-10-26 12:58:00 +02008102/* parse the "crt" server keyword */
8103static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8104{
8105 if (!*args[*cur_arg + 1]) {
8106 if (err)
8107 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8108 return ERR_ALERT | ERR_FATAL;
8109 }
8110
Willy Tarreauef934602016-12-22 23:12:01 +01008111 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008112 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008113 else
8114 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8115
8116 return 0;
8117}
Emeric Brunef42d922012-10-11 16:11:36 +02008118
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008119/* parse the "no-check-ssl" server keyword */
8120static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8121{
8122 newsrv->check.use_ssl = 0;
8123 free(newsrv->ssl_ctx.ciphers);
8124 newsrv->ssl_ctx.ciphers = NULL;
8125 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8126 return 0;
8127}
8128
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008129/* parse the "no-send-proxy-v2-ssl" server keyword */
8130static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8131{
8132 newsrv->pp_opts &= ~SRV_PP_V2;
8133 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8134 return 0;
8135}
8136
8137/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8138static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8139{
8140 newsrv->pp_opts &= ~SRV_PP_V2;
8141 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8142 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8143 return 0;
8144}
8145
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008146/* parse the "no-ssl" server keyword */
8147static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8148{
8149 newsrv->use_ssl = 0;
8150 free(newsrv->ssl_ctx.ciphers);
8151 newsrv->ssl_ctx.ciphers = NULL;
8152 return 0;
8153}
8154
Olivier Houchard522eea72017-11-03 16:27:47 +01008155/* parse the "allow-0rtt" server keyword */
8156static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8157{
8158 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8159 return 0;
8160}
8161
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008162/* parse the "no-ssl-reuse" server keyword */
8163static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8164{
8165 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8166 return 0;
8167}
8168
Emeric Brunf9c5c472012-10-11 15:28:34 +02008169/* parse the "no-tls-tickets" server keyword */
8170static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8171{
8172 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8173 return 0;
8174}
David Safb76832014-05-08 23:42:08 -04008175/* parse the "send-proxy-v2-ssl" server keyword */
8176static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8177{
8178 newsrv->pp_opts |= SRV_PP_V2;
8179 newsrv->pp_opts |= SRV_PP_V2_SSL;
8180 return 0;
8181}
8182
8183/* parse the "send-proxy-v2-ssl-cn" server keyword */
8184static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8185{
8186 newsrv->pp_opts |= SRV_PP_V2;
8187 newsrv->pp_opts |= SRV_PP_V2_SSL;
8188 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8189 return 0;
8190}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008191
Willy Tarreau732eac42015-07-09 11:40:25 +02008192/* parse the "sni" server keyword */
8193static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8194{
8195#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8196 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8197 return ERR_ALERT | ERR_FATAL;
8198#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008199 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008200
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008201 arg = args[*cur_arg + 1];
8202 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008203 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8204 return ERR_ALERT | ERR_FATAL;
8205 }
8206
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008207 free(newsrv->sni_expr);
8208 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008209
Willy Tarreau732eac42015-07-09 11:40:25 +02008210 return 0;
8211#endif
8212}
8213
Willy Tarreau92faadf2012-10-10 23:04:25 +02008214/* parse the "ssl" server keyword */
8215static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8216{
8217 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008218 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8219 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008220#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8221 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8222 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8223#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008224 return 0;
8225}
8226
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008227/* parse the "ssl-reuse" server keyword */
8228static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8229{
8230 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8231 return 0;
8232}
8233
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008234/* parse the "tls-tickets" server keyword */
8235static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8236{
8237 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8238 return 0;
8239}
8240
Emeric Brunef42d922012-10-11 16:11:36 +02008241/* parse the "verify" server keyword */
8242static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8243{
8244 if (!*args[*cur_arg + 1]) {
8245 if (err)
8246 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8247 return ERR_ALERT | ERR_FATAL;
8248 }
8249
8250 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008251 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008252 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008253 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008254 else {
8255 if (err)
8256 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8257 args[*cur_arg], args[*cur_arg + 1]);
8258 return ERR_ALERT | ERR_FATAL;
8259 }
8260
Evan Broderbe554312013-06-27 00:05:25 -07008261 return 0;
8262}
8263
8264/* parse the "verifyhost" server keyword */
8265static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8266{
8267 if (!*args[*cur_arg + 1]) {
8268 if (err)
8269 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8270 return ERR_ALERT | ERR_FATAL;
8271 }
8272
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008273 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008274 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8275
Emeric Brunef42d922012-10-11 16:11:36 +02008276 return 0;
8277}
8278
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008279/* parse the "ssl-default-bind-options" keyword in global section */
8280static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8281 struct proxy *defpx, const char *file, int line,
8282 char **err) {
8283 int i = 1;
8284
8285 if (*(args[i]) == 0) {
8286 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8287 return -1;
8288 }
8289 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008290 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008291 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008292 else if (!strcmp(args[i], "prefer-client-ciphers"))
8293 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008294 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8295 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8296 i++;
8297 else {
8298 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8299 return -1;
8300 }
8301 }
8302 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008303 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8304 return -1;
8305 }
8306 i++;
8307 }
8308 return 0;
8309}
8310
8311/* parse the "ssl-default-server-options" keyword in global section */
8312static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8313 struct proxy *defpx, const char *file, int line,
8314 char **err) {
8315 int i = 1;
8316
8317 if (*(args[i]) == 0) {
8318 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8319 return -1;
8320 }
8321 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008322 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008323 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008324 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8325 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8326 i++;
8327 else {
8328 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8329 return -1;
8330 }
8331 }
8332 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008333 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8334 return -1;
8335 }
8336 i++;
8337 }
8338 return 0;
8339}
8340
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008341/* parse the "ca-base" / "crt-base" keywords in global section.
8342 * Returns <0 on alert, >0 on warning, 0 on success.
8343 */
8344static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8345 struct proxy *defpx, const char *file, int line,
8346 char **err)
8347{
8348 char **target;
8349
Willy Tarreauef934602016-12-22 23:12:01 +01008350 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008351
8352 if (too_many_args(1, args, err, NULL))
8353 return -1;
8354
8355 if (*target) {
8356 memprintf(err, "'%s' already specified.", args[0]);
8357 return -1;
8358 }
8359
8360 if (*(args[1]) == 0) {
8361 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8362 return -1;
8363 }
8364 *target = strdup(args[1]);
8365 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008366}
8367
8368/* parse the "ssl-mode-async" keyword in global section.
8369 * Returns <0 on alert, >0 on warning, 0 on success.
8370 */
8371static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8372 struct proxy *defpx, const char *file, int line,
8373 char **err)
8374{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008375#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008376 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008377 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008378 return 0;
8379#else
8380 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8381 return -1;
8382#endif
8383}
8384
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008385#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008386static int ssl_check_async_engine_count(void) {
8387 int err_code = 0;
8388
Emeric Brun3854e012017-05-17 20:42:48 +02008389 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008390 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008391 err_code = ERR_ABORT;
8392 }
8393 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008394}
8395
Grant Zhang872f9c22017-01-21 01:10:18 +00008396/* parse the "ssl-engine" keyword in global section.
8397 * Returns <0 on alert, >0 on warning, 0 on success.
8398 */
8399static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8400 struct proxy *defpx, const char *file, int line,
8401 char **err)
8402{
8403 char *algo;
8404 int ret = -1;
8405
8406 if (*(args[1]) == 0) {
8407 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8408 return ret;
8409 }
8410
8411 if (*(args[2]) == 0) {
8412 /* if no list of algorithms is given, it defaults to ALL */
8413 algo = strdup("ALL");
8414 goto add_engine;
8415 }
8416
8417 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8418 if (strcmp(args[2], "algo") != 0) {
8419 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8420 return ret;
8421 }
8422
8423 if (*(args[3]) == 0) {
8424 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8425 return ret;
8426 }
8427 algo = strdup(args[3]);
8428
8429add_engine:
8430 if (ssl_init_single_engine(args[1], algo)==0) {
8431 openssl_engines_initialized++;
8432 ret = 0;
8433 }
8434 free(algo);
8435 return ret;
8436}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008437#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008438
Willy Tarreauf22e9682016-12-21 23:23:19 +01008439/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8440 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8441 */
8442static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8443 struct proxy *defpx, const char *file, int line,
8444 char **err)
8445{
8446 char **target;
8447
Willy Tarreauef934602016-12-22 23:12:01 +01008448 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008449
8450 if (too_many_args(1, args, err, NULL))
8451 return -1;
8452
8453 if (*(args[1]) == 0) {
8454 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8455 return -1;
8456 }
8457
8458 free(*target);
8459 *target = strdup(args[1]);
8460 return 0;
8461}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008462
8463#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8464/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8465 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8466 */
8467static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8468 struct proxy *defpx, const char *file, int line,
8469 char **err)
8470{
8471 char **target;
8472
8473 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8474
8475 if (too_many_args(1, args, err, NULL))
8476 return -1;
8477
8478 if (*(args[1]) == 0) {
8479 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8480 return -1;
8481 }
8482
8483 free(*target);
8484 *target = strdup(args[1]);
8485 return 0;
8486}
8487#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008488
Willy Tarreau9ceda382016-12-21 23:13:03 +01008489/* parse various global tune.ssl settings consisting in positive integers.
8490 * Returns <0 on alert, >0 on warning, 0 on success.
8491 */
8492static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8493 struct proxy *defpx, const char *file, int line,
8494 char **err)
8495{
8496 int *target;
8497
8498 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8499 target = &global.tune.sslcachesize;
8500 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008501 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008502 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008503 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008504 else if (strcmp(args[0], "maxsslconn") == 0)
8505 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008506 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8507 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008508 else {
8509 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8510 return -1;
8511 }
8512
8513 if (too_many_args(1, args, err, NULL))
8514 return -1;
8515
8516 if (*(args[1]) == 0) {
8517 memprintf(err, "'%s' expects an integer argument.", args[0]);
8518 return -1;
8519 }
8520
8521 *target = atoi(args[1]);
8522 if (*target < 0) {
8523 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8524 return -1;
8525 }
8526 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008527}
8528
8529static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8530 struct proxy *defpx, const char *file, int line,
8531 char **err)
8532{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008533 int ret;
8534
8535 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8536 if (ret != 0)
8537 return ret;
8538
Willy Tarreaubafbe012017-11-24 17:34:44 +01008539 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008540 memprintf(err, "'%s' is already configured.", args[0]);
8541 return -1;
8542 }
8543
Willy Tarreaubafbe012017-11-24 17:34:44 +01008544 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8545 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008546 memprintf(err, "Out of memory error.");
8547 return -1;
8548 }
8549 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008550}
8551
8552/* parse "ssl.force-private-cache".
8553 * Returns <0 on alert, >0 on warning, 0 on success.
8554 */
8555static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8556 struct proxy *defpx, const char *file, int line,
8557 char **err)
8558{
8559 if (too_many_args(0, args, err, NULL))
8560 return -1;
8561
Willy Tarreauef934602016-12-22 23:12:01 +01008562 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008563 return 0;
8564}
8565
8566/* parse "ssl.lifetime".
8567 * Returns <0 on alert, >0 on warning, 0 on success.
8568 */
8569static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8570 struct proxy *defpx, const char *file, int line,
8571 char **err)
8572{
8573 const char *res;
8574
8575 if (too_many_args(1, args, err, NULL))
8576 return -1;
8577
8578 if (*(args[1]) == 0) {
8579 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8580 return -1;
8581 }
8582
Willy Tarreauef934602016-12-22 23:12:01 +01008583 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008584 if (res) {
8585 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8586 return -1;
8587 }
8588 return 0;
8589}
8590
8591#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008592/* parse "ssl-dh-param-file".
8593 * Returns <0 on alert, >0 on warning, 0 on success.
8594 */
8595static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8596 struct proxy *defpx, const char *file, int line,
8597 char **err)
8598{
8599 if (too_many_args(1, args, err, NULL))
8600 return -1;
8601
8602 if (*(args[1]) == 0) {
8603 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8604 return -1;
8605 }
8606
8607 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8608 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8609 return -1;
8610 }
8611 return 0;
8612}
8613
Willy Tarreau9ceda382016-12-21 23:13:03 +01008614/* parse "ssl.default-dh-param".
8615 * Returns <0 on alert, >0 on warning, 0 on success.
8616 */
8617static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8618 struct proxy *defpx, const char *file, int line,
8619 char **err)
8620{
8621 if (too_many_args(1, args, err, NULL))
8622 return -1;
8623
8624 if (*(args[1]) == 0) {
8625 memprintf(err, "'%s' expects an integer argument.", args[0]);
8626 return -1;
8627 }
8628
Willy Tarreauef934602016-12-22 23:12:01 +01008629 global_ssl.default_dh_param = atoi(args[1]);
8630 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008631 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8632 return -1;
8633 }
8634 return 0;
8635}
8636#endif
8637
8638
William Lallemand32af2032016-10-29 18:09:35 +02008639/* This function is used with TLS ticket keys management. It permits to browse
8640 * each reference. The variable <getnext> must contain the current node,
8641 * <end> point to the root node.
8642 */
8643#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8644static inline
8645struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8646{
8647 struct tls_keys_ref *ref = getnext;
8648
8649 while (1) {
8650
8651 /* Get next list entry. */
8652 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8653
8654 /* If the entry is the last of the list, return NULL. */
8655 if (&ref->list == end)
8656 return NULL;
8657
8658 return ref;
8659 }
8660}
8661
8662static inline
8663struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8664{
8665 int id;
8666 char *error;
8667
8668 /* If the reference starts by a '#', this is numeric id. */
8669 if (reference[0] == '#') {
8670 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8671 id = strtol(reference + 1, &error, 10);
8672 if (*error != '\0')
8673 return NULL;
8674
8675 /* Perform the unique id lookup. */
8676 return tlskeys_ref_lookupid(id);
8677 }
8678
8679 /* Perform the string lookup. */
8680 return tlskeys_ref_lookup(reference);
8681}
8682#endif
8683
8684
8685#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8686
8687static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8688
8689static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8690 return cli_io_handler_tlskeys_files(appctx);
8691}
8692
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008693/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8694 * (next index to be dumped), and cli.p0 (next key reference).
8695 */
William Lallemand32af2032016-10-29 18:09:35 +02008696static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8697
8698 struct stream_interface *si = appctx->owner;
8699
8700 switch (appctx->st2) {
8701 case STAT_ST_INIT:
8702 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008703 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008704 * later and restart at the state "STAT_ST_INIT".
8705 */
8706 chunk_reset(&trash);
8707
8708 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8709 chunk_appendf(&trash, "# id secret\n");
8710 else
8711 chunk_appendf(&trash, "# id (file)\n");
8712
Willy Tarreau06d80a92017-10-19 14:32:15 +02008713 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008714 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008715 return 0;
8716 }
8717
William Lallemand32af2032016-10-29 18:09:35 +02008718 /* Now, we start the browsing of the references lists.
8719 * Note that the following call to LIST_ELEM return bad pointer. The only
8720 * available field of this pointer is <list>. It is used with the function
8721 * tlskeys_list_get_next() for retruning the first available entry
8722 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008723 if (appctx->ctx.cli.p0 == NULL) {
8724 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8725 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008726 }
8727
8728 appctx->st2 = STAT_ST_LIST;
8729 /* fall through */
8730
8731 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008732 while (appctx->ctx.cli.p0) {
8733 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008734
8735 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008736 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008737 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008738
8739 if (appctx->ctx.cli.i1 == 0)
8740 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8741
William Lallemand32af2032016-10-29 18:09:35 +02008742 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008743 int head;
8744
8745 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8746 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008747 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008748 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008749
8750 chunk_reset(t2);
8751 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008752 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8753 sizeof(struct tls_sess_key),
8754 t2->area, t2->size);
8755 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8756 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008757
Willy Tarreau06d80a92017-10-19 14:32:15 +02008758 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008759 /* let's try again later from this stream. We add ourselves into
8760 * this stream's users so that it can remove us upon termination.
8761 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008762 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008763 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008764 return 0;
8765 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008766 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008767 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008768 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008769 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008770 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008771 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008772 /* let's try again later from this stream. We add ourselves into
8773 * this stream's users so that it can remove us upon termination.
8774 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008775 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008776 return 0;
8777 }
8778
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008779 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008780 break;
8781
8782 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008783 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008784 }
8785
8786 appctx->st2 = STAT_ST_FIN;
8787 /* fall through */
8788
8789 default:
8790 appctx->st2 = STAT_ST_FIN;
8791 return 1;
8792 }
8793 return 0;
8794}
8795
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008796/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008797static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008798{
William Lallemand32af2032016-10-29 18:09:35 +02008799 /* no parameter, shows only file list */
8800 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008801 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008802 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008803 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008804 }
8805
8806 if (args[2][0] == '*') {
8807 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008808 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008809 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008810 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8811 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008812 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008813 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008814 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008815 return 1;
8816 }
8817 }
William Lallemand32af2032016-10-29 18:09:35 +02008818 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008819 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008820}
8821
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008822static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008823{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008824 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008825 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008826
William Lallemand32af2032016-10-29 18:09:35 +02008827 /* Expect two parameters: the filename and the new new TLS key in encoding */
8828 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008829 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008830 appctx->ctx.cli.msg = "'set ssl tls-key' expects a filename and the new TLS key in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008831 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008832 return 1;
8833 }
8834
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008835 ref = tlskeys_ref_lookup_ref(args[3]);
8836 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008837 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008838 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008839 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008840 return 1;
8841 }
8842
Willy Tarreau1c913e42018-08-22 05:26:57 +02008843 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8844 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008845 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008846 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008847 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008848 return 1;
8849 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008850 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008851 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008852 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008853 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008854 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008855 return 1;
8856
8857}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008858#endif
William Lallemand32af2032016-10-29 18:09:35 +02008859
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008860static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008861{
8862#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8863 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008864 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008865
8866 if (!payload)
8867 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008868
8869 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008870 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008871 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008872 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008873 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008874 return 1;
8875 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008876
8877 /* remove \r and \n from the payload */
8878 for (i = 0, j = 0; payload[i]; i++) {
8879 if (payload[i] == '\r' || payload[i] == '\n')
8880 continue;
8881 payload[j++] = payload[i];
8882 }
8883 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008884
Willy Tarreau1c913e42018-08-22 05:26:57 +02008885 ret = base64dec(payload, j, trash.area, trash.size);
8886 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008887 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008888 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008889 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008890 return 1;
8891 }
8892
Willy Tarreau1c913e42018-08-22 05:26:57 +02008893 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008894 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8895 if (err) {
8896 memprintf(&err, "%s.\n", err);
8897 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008898 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008899 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008900 else {
8901 appctx->ctx.cli.severity = LOG_ERR;
8902 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8903 appctx->st0 = CLI_ST_PRINT;
8904 }
William Lallemand32af2032016-10-29 18:09:35 +02008905 return 1;
8906 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008907 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008908 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008909 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008910 return 1;
8911#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008912 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008913 appctx->ctx.cli.msg = "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008914 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008915 return 1;
8916#endif
8917
8918}
8919
8920/* register cli keywords */
8921static struct cli_kw_list cli_kws = {{ },{
8922#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8923 { { "show", "tls-keys", NULL }, "show tls-keys [id|*]: show tls keys references or dump tls ticket keys when id specified", cli_parse_show_tlskeys, NULL },
Lukas Tribusf4bbc432017-10-24 12:26:31 +02008924 { { "set", "ssl", "tls-key", NULL }, "set ssl tls-key [id|keyfile] <tlskey>: set the next TLS key for the <id> or <keyfile> listener to <tlskey>", cli_parse_set_tlskeys, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008925#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008926 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008927 { { NULL }, NULL, NULL, NULL }
8928}};
8929
8930
Willy Tarreau7875d092012-09-10 08:20:03 +02008931/* Note: must not be declared <const> as its list will be overwritten.
8932 * Please take care of keeping this list alphabetically sorted.
8933 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008934static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008935 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008936 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008937#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8938 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8939#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008940 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008941#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8942 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8943#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008944 { "ssl_bc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008945 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008946 { "ssl_bc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008947 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Patrick Hemmer41966772018-04-28 19:15:48 -04008948#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008949 { "ssl_bc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmer41966772018-04-28 19:15:48 -04008950#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008951#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8952 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8953#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008954 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8955 { "ssl_c_ca_err_depth", smp_fetch_ssl_c_ca_err_depth, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008956 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008957 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008958 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8959 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8960 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8961 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8962 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8963 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8964 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8965 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008966 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008967 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8968 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008969 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008970 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8971 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8972 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8973 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8974 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8975 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8976 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008977 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008978 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008979 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008980 { "ssl_fc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008981 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008982 { "ssl_fc_has_crt", smp_fetch_ssl_fc_has_crt, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008983 { "ssl_fc_has_early", smp_fetch_ssl_fc_has_early, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008984 { "ssl_fc_has_sni", smp_fetch_ssl_fc_has_sni, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02008985 { "ssl_fc_is_resumed", smp_fetch_ssl_fc_is_resumed, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Bernard Spil13c53f82018-02-15 13:34:58 +01008986#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008987 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008988#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008989#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008990 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008991#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008992 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008993#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02008994 { "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008995#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008996 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008997#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008998 { "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008999#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009000#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9001 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9002#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009003#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009004 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009005#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009006 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9007 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9008 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9009 { "ssl_fc_cipherlist_xxh", smp_fetch_ssl_fc_cl_xxh64, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau7875d092012-09-10 08:20:03 +02009010 { NULL, NULL, 0, 0, 0 },
9011}};
9012
9013/* Note: must not be declared <const> as its list will be overwritten.
9014 * Please take care of keeping this list alphabetically sorted.
9015 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009016static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009017 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9018 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009019 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009020}};
9021
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009022/* Note: must not be declared <const> as its list will be overwritten.
9023 * Please take care of keeping this list alphabetically sorted, doing so helps
9024 * all code contributors.
9025 * Optional keywords are also declared with a NULL ->parse() function so that
9026 * the config parser can report an appropriate error when a known keyword was
9027 * not enabled.
9028 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009029static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009030 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009031 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9032 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9033 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009034#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9035 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9036#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009037 { "crl-file", ssl_bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01009038 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009039 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009040 { "no-ca-names", ssl_bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009041 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009042 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9043 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009044 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9045 { NULL, NULL, 0 },
9046};
9047
Willy Tarreau51fb7652012-09-18 18:24:39 +02009048static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009049 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009050 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9051 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9052 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9053 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9054 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9055 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009056#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9057 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9058#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009059 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9060 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9061 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9062 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9063 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9064 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9065 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9066 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9067 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9068 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009069 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009070 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009071 { "no-ca-names", bind_parse_no_ca_names, 0 }, /* do not send ca names to clients (ca_file related) */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009072 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9073 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9074 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9075 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009076 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009077 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9078 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009079 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9080 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009081 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9082 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9083 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9084 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9085 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009086 { NULL, NULL, 0 },
9087}};
Emeric Brun46591952012-05-18 15:47:34 +02009088
Willy Tarreau92faadf2012-10-10 23:04:25 +02009089/* Note: must not be declared <const> as its list will be overwritten.
9090 * Please take care of keeping this list alphabetically sorted, doing so helps
9091 * all code contributors.
9092 * Optional keywords are also declared with a NULL ->parse() function so that
9093 * the config parser can report an appropriate error when a known keyword was
9094 * not enabled.
9095 */
9096static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009097 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009098 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009099 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009100 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009101 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9102 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009103#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9104 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9105#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009106 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9107 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9108 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9109 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9110 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9111 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9112 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9113 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9114 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9115 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9116 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9117 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9118 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9119 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9120 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9121 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9122 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9123 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009124 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009125 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9126 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9127 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9128 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9129 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9130 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9131 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9132 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9133 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9134 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009135 { NULL, NULL, 0, 0 },
9136}};
9137
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009138static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009139 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9140 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009141 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009142 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9143 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009144#ifndef OPENSSL_NO_DH
9145 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9146#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009147 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009148#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009149 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009150#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009151 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9152#ifndef OPENSSL_NO_DH
9153 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9154#endif
9155 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9156 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9157 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9158 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009159 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009160 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9161 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009162#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9163 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9164 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9165#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009166 { 0, NULL, NULL },
9167}};
9168
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009169/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009170static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009171 .snd_buf = ssl_sock_from_buf,
9172 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009173 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009174 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009175 .rcv_pipe = NULL,
9176 .snd_pipe = NULL,
9177 .shutr = NULL,
9178 .shutw = ssl_sock_shutw,
9179 .close = ssl_sock_close,
9180 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009181 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009182 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009183 .prepare_srv = ssl_sock_prepare_srv_ctx,
9184 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009185 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009186 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009187};
9188
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009189enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9190 struct session *sess, struct stream *s, int flags)
9191{
9192 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009193 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009194
9195 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009196 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009197
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009198 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009199 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009200 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009201 s->req.flags |= CF_READ_NULL;
9202 return ACT_RET_YIELD;
9203 }
9204 }
9205 return (ACT_RET_CONT);
9206}
9207
9208static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9209{
9210 rule->action_ptr = ssl_action_wait_for_hs;
9211
9212 return ACT_RET_PRS_OK;
9213}
9214
9215static struct action_kw_list http_req_actions = {ILH, {
9216 { "wait-for-handshake", ssl_parse_wait_for_hs },
9217 { /* END */ }
9218}};
9219
Daniel Jakots54ffb912015-11-06 20:02:41 +01009220#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009221
9222static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9223{
9224 if (ptr) {
9225 chunk_destroy(ptr);
9226 free(ptr);
9227 }
9228}
9229
9230#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009231static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9232{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009233 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009234}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009235
Emeric Brun46591952012-05-18 15:47:34 +02009236__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009237static void __ssl_sock_init(void)
9238{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009239 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009240 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009241
Emeric Brun46591952012-05-18 15:47:34 +02009242 STACK_OF(SSL_COMP)* cm;
9243
Willy Tarreauef934602016-12-22 23:12:01 +01009244 if (global_ssl.listen_default_ciphers)
9245 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9246 if (global_ssl.connect_default_ciphers)
9247 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009248#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9249 if (global_ssl.listen_default_ciphersuites)
9250 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9251 if (global_ssl.connect_default_ciphersuites)
9252 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9253#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009254
Willy Tarreau13e14102016-12-22 20:25:26 +01009255 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009256 SSL_library_init();
9257 cm = SSL_COMP_get_compression_methods();
9258 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009259#ifdef USE_THREAD
9260 ssl_locking_init();
9261#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009262#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009263 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9264#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009265 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009266 ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01009267 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Willy Tarreau7875d092012-09-10 08:20:03 +02009268 sample_register_fetches(&sample_fetch_keywords);
9269 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009270 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02009271 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009272 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009273 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009274#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009275 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009276 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009277#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009278#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9279 hap_register_post_check(tlskeys_finalize_config);
9280#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009281
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009282 ptr = NULL;
9283 memprintf(&ptr, "Built with OpenSSL version : "
9284#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009285 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009286#else /* OPENSSL_IS_BORINGSSL */
9287 OPENSSL_VERSION_TEXT
9288 "\nRunning on OpenSSL version : %s%s",
9289 SSLeay_version(SSLEAY_VERSION),
9290 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9291#endif
9292 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9293#if OPENSSL_VERSION_NUMBER < 0x00907000L
9294 "no (library version too old)"
9295#elif defined(OPENSSL_NO_TLSEXT)
9296 "no (disabled via OPENSSL_NO_TLSEXT)"
9297#else
9298 "yes"
9299#endif
9300 "", ptr);
9301
9302 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9303#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9304 "yes"
9305#else
9306#ifdef OPENSSL_NO_TLSEXT
9307 "no (because of OPENSSL_NO_TLSEXT)"
9308#else
9309 "no (version might be too old, 0.9.8f min needed)"
9310#endif
9311#endif
9312 "", ptr);
9313
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009314 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9315 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9316 if (methodVersions[i].option)
9317 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009318
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009319 hap_register_build_opts(ptr, 1);
9320
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009321 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9322 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02009323
9324#ifndef OPENSSL_NO_DH
9325 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00009326 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009327#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009328#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009329 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009330#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02009331 /* Load SSL string for the verbose & debug mode. */
9332 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009333
9334 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02009335}
9336
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009337#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009338void ssl_free_engines(void) {
9339 struct ssl_engine_list *wl, *wlb;
9340 /* free up engine list */
9341 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9342 ENGINE_finish(wl->e);
9343 ENGINE_free(wl->e);
9344 LIST_DEL(&wl->list);
9345 free(wl);
9346 }
9347}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009348#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009349
Remi Gacogned3a23c32015-05-28 16:39:47 +02009350#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009351void ssl_free_dh(void) {
9352 if (local_dh_1024) {
9353 DH_free(local_dh_1024);
9354 local_dh_1024 = NULL;
9355 }
9356 if (local_dh_2048) {
9357 DH_free(local_dh_2048);
9358 local_dh_2048 = NULL;
9359 }
9360 if (local_dh_4096) {
9361 DH_free(local_dh_4096);
9362 local_dh_4096 = NULL;
9363 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009364 if (global_dh) {
9365 DH_free(global_dh);
9366 global_dh = NULL;
9367 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009368}
9369#endif
9370
9371__attribute__((destructor))
9372static void __ssl_sock_deinit(void)
9373{
9374#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009375 if (ssl_ctx_lru_tree) {
9376 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009377 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009378 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009379#endif
9380
9381 ERR_remove_state(0);
9382 ERR_free_strings();
9383
9384 EVP_cleanup();
9385
9386#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9387 CRYPTO_cleanup_all_ex_data();
9388#endif
9389}
9390
9391
Emeric Brun46591952012-05-18 15:47:34 +02009392/*
9393 * Local variables:
9394 * c-indent-level: 8
9395 * c-basic-offset: 8
9396 * End:
9397 */