blob: b6db4c575d4d2144d3eb3d71da71f4baef9de6ec [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
Rosen Penev68185952018-12-14 08:47:02 -080042#include <openssl/bn.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020043#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020044#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020045#include <openssl/x509.h>
46#include <openssl/x509v3.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020047#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010048#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020049#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010050#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020051#include <openssl/ocsp.h>
52#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020053#ifndef OPENSSL_NO_DH
54#include <openssl/dh.h>
55#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020056#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000057#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020058#endif
Emeric Brun46591952012-05-18 15:47:34 +020059
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020060#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000061#include <openssl/async.h>
62#endif
63
Rosen Penev68185952018-12-14 08:47:02 -080064#ifndef OPENSSL_VERSION
65#define OPENSSL_VERSION SSLEAY_VERSION
66#define OpenSSL_version(x) SSLeay_version(x)
67#define OpenSSL_version_num SSLeay
68#endif
69
70#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (LIBRESSL_VERSION_NUMBER < 0x20700000L)
71#define X509_getm_notBefore X509_get_notBefore
72#define X509_getm_notAfter X509_get_notAfter
73#endif
74
Christopher Faulet31af49d2015-06-09 17:29:50 +020075#include <import/lru.h>
76#include <import/xxhash.h>
77
Emeric Brun46591952012-05-18 15:47:34 +020078#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020079#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020080#include <common/compat.h>
81#include <common/config.h>
82#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020083#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010084#include <common/initcall.h>
Emeric Brun46591952012-05-18 15:47:34 +020085#include <common/standard.h>
86#include <common/ticks.h>
87#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010088#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010089#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Emeric Brunfc0421f2012-09-07 17:30:07 +020091#include <ebsttree.h>
92
William Lallemand32af2032016-10-29 18:09:35 +020093#include <types/applet.h>
94#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020095#include <types/global.h>
96#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020097#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020098
Willy Tarreau7875d092012-09-10 08:20:03 +020099#include <proto/acl.h>
100#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +0200101#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +0200102#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +0200103#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/fd.h>
105#include <proto/freq_ctr.h>
106#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +0200107#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +0200108#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200109#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +0100110#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +0200111#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +0200112#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +0200113#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200114#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200115#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200116#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200117#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200118#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200119#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200120#include <proto/task.h>
121
Willy Tarreau518cedd2014-02-17 15:43:01 +0100122/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200123#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100124#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100125#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200126#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
127
Emeric Brunf282a812012-09-21 15:27:54 +0200128/* bits 0xFFFF0000 are reserved to store verify errors */
129
130/* Verify errors macros */
131#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
132#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
133#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
134
135#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
136#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
137#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200138
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100139/* Supported hash function for TLS tickets */
140#ifdef OPENSSL_NO_SHA256
141#define HASH_FUNCT EVP_sha1
142#else
143#define HASH_FUNCT EVP_sha256
144#endif /* OPENSSL_NO_SHA256 */
145
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200146/* ssl_methods flags for ssl options */
147#define MC_SSL_O_ALL 0x0000
148#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
149#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
150#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
151#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200152#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200153
154/* ssl_methods versions */
155enum {
156 CONF_TLSV_NONE = 0,
157 CONF_TLSV_MIN = 1,
158 CONF_SSLV3 = 1,
159 CONF_TLSV10 = 2,
160 CONF_TLSV11 = 3,
161 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200162 CONF_TLSV13 = 5,
163 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200164};
165
Emeric Brun850efd52014-01-29 12:24:34 +0100166/* server and bind verify method, it uses a global value as default */
167enum {
168 SSL_SOCK_VERIFY_DEFAULT = 0,
169 SSL_SOCK_VERIFY_REQUIRED = 1,
170 SSL_SOCK_VERIFY_OPTIONAL = 2,
171 SSL_SOCK_VERIFY_NONE = 3,
172};
173
William Lallemand3f85c9a2017-10-09 16:30:50 +0200174
Willy Tarreau71b734c2014-01-28 15:19:44 +0100175int sslconns = 0;
176int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100177static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100178int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200179
Willy Tarreauef934602016-12-22 23:12:01 +0100180static struct {
181 char *crt_base; /* base directory path for certificates */
182 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000183 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100184
185 char *listen_default_ciphers;
186 char *connect_default_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200187#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
188 char *listen_default_ciphersuites;
189 char *connect_default_ciphersuites;
190#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100191 int listen_default_ssloptions;
192 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 struct tls_version_filter listen_default_sslmethods;
194 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100195
196 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
197 unsigned int life_time; /* SSL session lifetime in seconds */
198 unsigned int max_record; /* SSL max record size */
199 unsigned int default_dh_param; /* SSL maximum DH parameter size */
200 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100201 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100202} global_ssl = {
203#ifdef LISTEN_DEFAULT_CIPHERS
204 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
205#endif
206#ifdef CONNECT_DEFAULT_CIPHERS
207 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
208#endif
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200209#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
210#ifdef LISTEN_DEFAULT_CIPHERSUITES
211 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
212#endif
213#ifdef CONNECT_DEFAULT_CIPHERSUITES
214 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
215#endif
216#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100217 .listen_default_ssloptions = BC_SSL_O_NONE,
218 .connect_default_ssloptions = SRV_SSL_O_NONE,
219
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200220 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
221 .listen_default_sslmethods.min = CONF_TLSV_NONE,
222 .listen_default_sslmethods.max = CONF_TLSV_NONE,
223 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
224 .connect_default_sslmethods.min = CONF_TLSV_NONE,
225 .connect_default_sslmethods.max = CONF_TLSV_NONE,
226
Willy Tarreauef934602016-12-22 23:12:01 +0100227#ifdef DEFAULT_SSL_MAX_RECORD
228 .max_record = DEFAULT_SSL_MAX_RECORD,
229#endif
230 .default_dh_param = SSL_DEFAULT_DH_PARAM,
231 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100232 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100233};
234
Rosen Penev68185952018-12-14 08:47:02 -0800235#if defined(USE_THREAD) && ((OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER))
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100236
Emeric Brun821bb9b2017-06-15 16:37:39 +0200237static HA_RWLOCK_T *ssl_rwlocks;
238
239
240unsigned long ssl_id_function(void)
241{
242 return (unsigned long)tid;
243}
244
245void ssl_locking_function(int mode, int n, const char * file, int line)
246{
247 if (mode & CRYPTO_LOCK) {
248 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100249 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200250 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100251 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200252 }
253 else {
254 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100255 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200256 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100257 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200258 }
259}
260
261static int ssl_locking_init(void)
262{
263 int i;
264
265 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
266 if (!ssl_rwlocks)
267 return -1;
268
269 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100270 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200271
272 CRYPTO_set_id_callback(ssl_id_function);
273 CRYPTO_set_locking_callback(ssl_locking_function);
274
275 return 0;
276}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100277
Emeric Brun821bb9b2017-06-15 16:37:39 +0200278#endif
279
280
281
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100282/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100283struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100284 unsigned long long int xxh64;
285 unsigned char ciphersuite_len;
286 char ciphersuite[0];
287};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100288struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100289static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200290static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100291
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100292static int ssl_pkey_info_index = -1;
293
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200294#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
295struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
296#endif
297
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200298#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000299static unsigned int openssl_engines_initialized;
300struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
301struct ssl_engine_list {
302 struct list list;
303 ENGINE *e;
304};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200305#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000306
Remi Gacogne8de54152014-07-15 11:36:40 +0200307#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200308static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200309static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200310static DH *local_dh_1024 = NULL;
311static DH *local_dh_2048 = NULL;
312static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100313static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200314#endif /* OPENSSL_NO_DH */
315
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100316#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200317/* X509V3 Extensions that will be added on generated certificates */
318#define X509V3_EXT_SIZE 5
319static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
320 "basicConstraints",
321 "nsComment",
322 "subjectKeyIdentifier",
323 "authorityKeyIdentifier",
324 "keyUsage",
325};
326static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
327 "CA:FALSE",
328 "\"OpenSSL Generated Certificate\"",
329 "hash",
330 "keyid,issuer:always",
331 "nonRepudiation,digitalSignature,keyEncipherment"
332};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200333/* LRU cache to store generated certificate */
334static struct lru64_head *ssl_ctx_lru_tree = NULL;
335static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200336static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100337__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200338
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200339#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
340
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100341static struct ssl_bind_kw ssl_bind_kws[];
342
yanbzhube2774d2015-12-10 15:07:30 -0500343#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
344/* The order here matters for picking a default context,
345 * keep the most common keytype at the bottom of the list
346 */
347const char *SSL_SOCK_KEYTYPE_NAMES[] = {
348 "dsa",
349 "ecdsa",
350 "rsa"
351};
352#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100353#else
354#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500355#endif
356
William Lallemandc3cd35f2017-11-28 11:04:43 +0100357static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100358static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
359
360#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
361
362#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
363 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
364
365#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
366 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200367
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100368/*
369 * This function gives the detail of the SSL error. It is used only
370 * if the debug mode and the verbose mode are activated. It dump all
371 * the SSL error until the stack was empty.
372 */
373static forceinline void ssl_sock_dump_errors(struct connection *conn)
374{
375 unsigned long ret;
376
377 if (unlikely(global.mode & MODE_DEBUG)) {
378 while(1) {
379 ret = ERR_get_error();
380 if (ret == 0)
381 return;
382 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200383 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100384 ERR_func_error_string(ret), ERR_reason_error_string(ret));
385 }
386 }
387}
388
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200389#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500390/*
391 * struct alignment works here such that the key.key is the same as key_data
392 * Do not change the placement of key_data
393 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200394struct certificate_ocsp {
395 struct ebmb_node key;
396 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200397 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200398 long expire;
399};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200400
yanbzhube2774d2015-12-10 15:07:30 -0500401struct ocsp_cbk_arg {
402 int is_single;
403 int single_kt;
404 union {
405 struct certificate_ocsp *s_ocsp;
406 /*
407 * m_ocsp will have multiple entries dependent on key type
408 * Entry 0 - DSA
409 * Entry 1 - ECDSA
410 * Entry 2 - RSA
411 */
412 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
413 };
414};
415
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200416#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000417static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
418{
419 int err_code = ERR_ABORT;
420 ENGINE *engine;
421 struct ssl_engine_list *el;
422
423 /* grab the structural reference to the engine */
424 engine = ENGINE_by_id(engine_id);
425 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100426 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000427 goto fail_get;
428 }
429
430 if (!ENGINE_init(engine)) {
431 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100432 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000433 goto fail_init;
434 }
435
436 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100437 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000438 goto fail_set_method;
439 }
440
441 el = calloc(1, sizeof(*el));
442 el->e = engine;
443 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100444 nb_engines++;
445 if (global_ssl.async)
446 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000447 return 0;
448
449fail_set_method:
450 /* release the functional reference from ENGINE_init() */
451 ENGINE_finish(engine);
452
453fail_init:
454 /* release the structural reference from ENGINE_by_id() */
455 ENGINE_free(engine);
456
457fail_get:
458 return err_code;
459}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200460#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000461
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200462#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200463/*
464 * openssl async fd handler
465 */
466static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000467{
468 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000469
Emeric Brun3854e012017-05-17 20:42:48 +0200470 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000471 * to poll this fd until it is requested
472 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000473 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000474 fd_cant_recv(fd);
475
476 /* crypto engine is available, let's notify the associated
477 * connection that it can pursue its processing.
478 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000479 __conn_sock_want_recv(conn);
480 __conn_sock_want_send(conn);
481 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000482}
483
Emeric Brun3854e012017-05-17 20:42:48 +0200484/*
485 * openssl async delayed SSL_free handler
486 */
487static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000488{
489 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200490 OSSL_ASYNC_FD all_fd[32];
491 size_t num_all_fds = 0;
492 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493
Emeric Brun3854e012017-05-17 20:42:48 +0200494 /* We suppose that the async job for a same SSL *
495 * are serialized. So if we are awake it is
496 * because the running job has just finished
497 * and we can remove all async fds safely
498 */
499 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
500 if (num_all_fds > 32) {
501 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
502 return;
503 }
504
505 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
506 for (i=0 ; i < num_all_fds ; i++)
507 fd_remove(all_fd[i]);
508
509 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000510 SSL_free(ssl);
Emeric Brun7ad43e72018-10-10 14:51:02 +0200511 HA_ATOMIC_SUB(&sslconns, 1);
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200512 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000514/*
Emeric Brun3854e012017-05-17 20:42:48 +0200515 * function used to manage a returned SSL_ERROR_WANT_ASYNC
516 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517 */
Emeric Brun3854e012017-05-17 20:42:48 +0200518static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000519{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100520 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200521 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000522 size_t num_add_fds = 0;
523 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200524 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000525
526 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
527 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200528 if (num_add_fds > 32 || num_del_fds > 32) {
529 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 +0000530 return;
531 }
532
Emeric Brun3854e012017-05-17 20:42:48 +0200533 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000534
Emeric Brun3854e012017-05-17 20:42:48 +0200535 /* We remove unused fds from the fdtab */
536 for (i=0 ; i < num_del_fds ; i++)
537 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000538
Emeric Brun3854e012017-05-17 20:42:48 +0200539 /* We add new fds to the fdtab */
540 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100541 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000542 }
543
Emeric Brun3854e012017-05-17 20:42:48 +0200544 num_add_fds = 0;
545 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
546 if (num_add_fds > 32) {
547 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
548 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000549 }
Emeric Brun3854e012017-05-17 20:42:48 +0200550
551 /* We activate the polling for all known async fds */
552 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000553 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200554 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000555 /* To ensure that the fd cache won't be used
556 * We'll prefer to catch a real RD event
557 * because handling an EAGAIN on this fd will
558 * result in a context switch and also
559 * some engines uses a fd in blocking mode.
560 */
561 fd_cant_recv(add_fd[i]);
562 }
Emeric Brun3854e012017-05-17 20:42:48 +0200563
564 /* We must also prevent the conn_handler
565 * to be called until a read event was
566 * polled on an async fd
567 */
568 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000569}
570#endif
571
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200572/*
573 * This function returns the number of seconds elapsed
574 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
575 * date presented un ASN1_GENERALIZEDTIME.
576 *
577 * In parsing error case, it returns -1.
578 */
579static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
580{
581 long epoch;
582 char *p, *end;
583 const unsigned short month_offset[12] = {
584 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
585 };
586 int year, month;
587
588 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
589
590 p = (char *)d->data;
591 end = p + d->length;
592
593 if (end - p < 4) return -1;
594 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
595 p += 4;
596 if (end - p < 2) return -1;
597 month = 10 * (p[0] - '0') + p[1] - '0';
598 if (month < 1 || month > 12) return -1;
599 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
600 We consider leap years and the current month (<marsh or not) */
601 epoch = ( ((year - 1970) * 365)
602 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
603 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
604 + month_offset[month-1]
605 ) * 24 * 60 * 60;
606 p += 2;
607 if (end - p < 2) return -1;
608 /* Add the number of seconds of completed days of current month */
609 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
610 p += 2;
611 if (end - p < 2) return -1;
612 /* Add the completed hours of the current day */
613 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
614 p += 2;
615 if (end - p < 2) return -1;
616 /* Add the completed minutes of the current hour */
617 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
618 p += 2;
619 if (p == end) return -1;
620 /* Test if there is available seconds */
621 if (p[0] < '0' || p[0] > '9')
622 goto nosec;
623 if (end - p < 2) return -1;
624 /* Add the seconds of the current minute */
625 epoch += 10 * (p[0] - '0') + p[1] - '0';
626 p += 2;
627 if (p == end) return -1;
628 /* Ignore seconds float part if present */
629 if (p[0] == '.') {
630 do {
631 if (++p == end) return -1;
632 } while (p[0] >= '0' && p[0] <= '9');
633 }
634
635nosec:
636 if (p[0] == 'Z') {
637 if (end - p != 1) return -1;
638 return epoch;
639 }
640 else if (p[0] == '+') {
641 if (end - p != 5) return -1;
642 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700643 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 +0200644 }
645 else if (p[0] == '-') {
646 if (end - p != 5) return -1;
647 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700648 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 +0200649 }
650
651 return -1;
652}
653
Emeric Brun1d3865b2014-06-20 15:37:32 +0200654static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200655
656/* This function starts to check if the OCSP response (in DER format) contained
657 * in chunk 'ocsp_response' is valid (else exits on error).
658 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
659 * contained in the OCSP Response and exits on error if no match.
660 * If it's a valid OCSP Response:
661 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
662 * pointed by 'ocsp'.
663 * If 'ocsp' is NULL, the function looks up into the OCSP response's
664 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
665 * from the response) and exits on error if not found. Finally, If an OCSP response is
666 * already present in the container, it will be overwritten.
667 *
668 * Note: OCSP response containing more than one OCSP Single response is not
669 * considered valid.
670 *
671 * Returns 0 on success, 1 in error case.
672 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200673static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
674 struct certificate_ocsp *ocsp,
675 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200676{
677 OCSP_RESPONSE *resp;
678 OCSP_BASICRESP *bs = NULL;
679 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200680 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200681 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200682 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200683 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200684 int reason;
685 int ret = 1;
686
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200687 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
688 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200689 if (!resp) {
690 memprintf(err, "Unable to parse OCSP response");
691 goto out;
692 }
693
694 rc = OCSP_response_status(resp);
695 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
696 memprintf(err, "OCSP response status not successful");
697 goto out;
698 }
699
700 bs = OCSP_response_get1_basic(resp);
701 if (!bs) {
702 memprintf(err, "Failed to get basic response from OCSP Response");
703 goto out;
704 }
705
706 count_sr = OCSP_resp_count(bs);
707 if (count_sr > 1) {
708 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
709 goto out;
710 }
711
712 sr = OCSP_resp_get0(bs, 0);
713 if (!sr) {
714 memprintf(err, "Failed to get OCSP single response");
715 goto out;
716 }
717
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200718 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
719
Emeric Brun4147b2e2014-06-16 18:36:30 +0200720 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200721 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200722 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200723 goto out;
724 }
725
Emeric Brun13a6b482014-06-20 15:44:34 +0200726 if (!nextupd) {
727 memprintf(err, "OCSP single response: missing nextupdate");
728 goto out;
729 }
730
Emeric Brunc8b27b62014-06-19 14:16:17 +0200731 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200732 if (!rc) {
733 memprintf(err, "OCSP single response: no longer valid.");
734 goto out;
735 }
736
737 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200738 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200739 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
740 goto out;
741 }
742 }
743
744 if (!ocsp) {
745 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
746 unsigned char *p;
747
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200748 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200749 if (!rc) {
750 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
751 goto out;
752 }
753
754 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
755 memprintf(err, "OCSP single response: Certificate ID too long");
756 goto out;
757 }
758
759 p = key;
760 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200761 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200762 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
763 if (!ocsp) {
764 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
765 goto out;
766 }
767 }
768
769 /* According to comments on "chunk_dup", the
770 previous chunk buffer will be freed */
771 if (!chunk_dup(&ocsp->response, ocsp_response)) {
772 memprintf(err, "OCSP response: Memory allocation error");
773 goto out;
774 }
775
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200776 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
777
Emeric Brun4147b2e2014-06-16 18:36:30 +0200778 ret = 0;
779out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100780 ERR_clear_error();
781
Emeric Brun4147b2e2014-06-16 18:36:30 +0200782 if (bs)
783 OCSP_BASICRESP_free(bs);
784
785 if (resp)
786 OCSP_RESPONSE_free(resp);
787
788 return ret;
789}
790/*
791 * External function use to update the OCSP response in the OCSP response's
792 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
793 * to update in DER format.
794 *
795 * Returns 0 on success, 1 in error case.
796 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200797int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200798{
799 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
800}
801
802/*
803 * This function load the OCSP Resonse in DER format contained in file at
804 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
805 *
806 * Returns 0 on success, 1 in error case.
807 */
808static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
809{
810 int fd = -1;
811 int r = 0;
812 int ret = 1;
813
814 fd = open(ocsp_path, O_RDONLY);
815 if (fd == -1) {
816 memprintf(err, "Error opening OCSP response file");
817 goto end;
818 }
819
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200820 trash.data = 0;
821 while (trash.data < trash.size) {
822 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200823 if (r < 0) {
824 if (errno == EINTR)
825 continue;
826
827 memprintf(err, "Error reading OCSP response from file");
828 goto end;
829 }
830 else if (r == 0) {
831 break;
832 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200833 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200834 }
835
836 close(fd);
837 fd = -1;
838
839 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
840end:
841 if (fd != -1)
842 close(fd);
843
844 return ret;
845}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100846#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200847
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100848#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
849static 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)
850{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100851 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100852 struct tls_sess_key *keys;
853 struct connection *conn;
854 int head;
855 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100856 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200858 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200859 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100860 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
861
862 keys = ref->tlskeys;
863 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100864
865 if (enc) {
866 memcpy(key_name, keys[head].name, 16);
867
868 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100869 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100870
871 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100872 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100873
874 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100875 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100876 } else {
877 for (i = 0; i < TLS_TICKETS_NO; i++) {
878 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
879 goto found;
880 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100881 ret = 0;
882 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100883
Christopher Faulet16f45c82018-02-16 11:23:49 +0100884 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100885 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
886 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 +0100887 goto end;
888
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100889 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100890 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100891 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100892 end:
893 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
894 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200895}
896
897struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
898{
899 struct tls_keys_ref *ref;
900
901 list_for_each_entry(ref, &tlskeys_reference, list)
902 if (ref->filename && strcmp(filename, ref->filename) == 0)
903 return ref;
904 return NULL;
905}
906
907struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
908{
909 struct tls_keys_ref *ref;
910
911 list_for_each_entry(ref, &tlskeys_reference, list)
912 if (ref->unique_id == unique_id)
913 return ref;
914 return NULL;
915}
916
Willy Tarreau83061a82018-07-13 11:56:34 +0200917void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
918 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100919{
920 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200921 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
922 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100923 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
924 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
925}
926
Willy Tarreau83061a82018-07-13 11:56:34 +0200927int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100928{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200929 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
930
931 if(!ref) {
932 memprintf(err, "Unable to locate the referenced filename: %s", filename);
933 return 1;
934 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100935 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200936 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100937}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200938
939/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100940 * automatic ids. It's called just after the basic checks. It returns
941 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200942 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100943static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200944{
945 int i = 0;
946 struct tls_keys_ref *ref, *ref2, *ref3;
947 struct list tkr = LIST_HEAD_INIT(tkr);
948
949 list_for_each_entry(ref, &tlskeys_reference, list) {
950 if (ref->unique_id == -1) {
951 /* Look for the first free id. */
952 while (1) {
953 list_for_each_entry(ref2, &tlskeys_reference, list) {
954 if (ref2->unique_id == i) {
955 i++;
956 break;
957 }
958 }
959 if (&ref2->list == &tlskeys_reference)
960 break;
961 }
962
963 /* Uses the unique id and increment it for the next entry. */
964 ref->unique_id = i;
965 i++;
966 }
967 }
968
969 /* This sort the reference list by id. */
970 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
971 LIST_DEL(&ref->list);
972 list_for_each_entry(ref3, &tkr, list) {
973 if (ref->unique_id < ref3->unique_id) {
974 LIST_ADDQ(&ref3->list, &ref->list);
975 break;
976 }
977 }
978 if (&ref3->list == &tkr)
979 LIST_ADDQ(&tkr, &ref->list);
980 }
981
982 /* swap root */
983 LIST_ADD(&tkr, &tlskeys_reference);
984 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100985 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200986}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100987#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
988
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100989#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500990int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
991{
992 switch (evp_keytype) {
993 case EVP_PKEY_RSA:
994 return 2;
995 case EVP_PKEY_DSA:
996 return 0;
997 case EVP_PKEY_EC:
998 return 1;
999 }
1000
1001 return -1;
1002}
1003
Emeric Brun4147b2e2014-06-16 18:36:30 +02001004/*
1005 * Callback used to set OCSP status extension content in server hello.
1006 */
1007int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1008{
yanbzhube2774d2015-12-10 15:07:30 -05001009 struct certificate_ocsp *ocsp;
1010 struct ocsp_cbk_arg *ocsp_arg;
1011 char *ssl_buf;
1012 EVP_PKEY *ssl_pkey;
1013 int key_type;
1014 int index;
1015
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001016 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001017
1018 ssl_pkey = SSL_get_privatekey(ssl);
1019 if (!ssl_pkey)
1020 return SSL_TLSEXT_ERR_NOACK;
1021
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001022 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001023
1024 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1025 ocsp = ocsp_arg->s_ocsp;
1026 else {
1027 /* For multiple certs per context, we have to find the correct OCSP response based on
1028 * the certificate type
1029 */
1030 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1031
1032 if (index < 0)
1033 return SSL_TLSEXT_ERR_NOACK;
1034
1035 ocsp = ocsp_arg->m_ocsp[index];
1036
1037 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001038
1039 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001040 !ocsp->response.area ||
1041 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001042 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001043 return SSL_TLSEXT_ERR_NOACK;
1044
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001045 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001046 if (!ssl_buf)
1047 return SSL_TLSEXT_ERR_NOACK;
1048
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001049 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1050 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001051
1052 return SSL_TLSEXT_ERR_OK;
1053}
1054
1055/*
1056 * This function enables the handling of OCSP status extension on 'ctx' if a
1057 * file name 'cert_path' suffixed using ".ocsp" is present.
1058 * To enable OCSP status extension, the issuer's certificate is mandatory.
1059 * It should be present in the certificate's extra chain builded from file
1060 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1061 * named 'cert_path' suffixed using '.issuer'.
1062 *
1063 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1064 * response. If file is empty or content is not a valid OCSP response,
1065 * OCSP status extension is enabled but OCSP response is ignored (a warning
1066 * is displayed).
1067 *
1068 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001069 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001070 */
1071static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1072{
1073
1074 BIO *in = NULL;
1075 X509 *x, *xi = NULL, *issuer = NULL;
1076 STACK_OF(X509) *chain = NULL;
1077 OCSP_CERTID *cid = NULL;
1078 SSL *ssl;
1079 char ocsp_path[MAXPATHLEN+1];
1080 int i, ret = -1;
1081 struct stat st;
1082 struct certificate_ocsp *ocsp = NULL, *iocsp;
1083 char *warn = NULL;
1084 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001085 pem_password_cb *passwd_cb;
1086 void *passwd_cb_userdata;
1087 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001088
1089 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1090
1091 if (stat(ocsp_path, &st))
1092 return 1;
1093
1094 ssl = SSL_new(ctx);
1095 if (!ssl)
1096 goto out;
1097
1098 x = SSL_get_certificate(ssl);
1099 if (!x)
1100 goto out;
1101
1102 /* Try to lookup for issuer in certificate extra chain */
1103#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1104 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1105#else
1106 chain = ctx->extra_certs;
1107#endif
1108 for (i = 0; i < sk_X509_num(chain); i++) {
1109 issuer = sk_X509_value(chain, i);
1110 if (X509_check_issued(issuer, x) == X509_V_OK)
1111 break;
1112 else
1113 issuer = NULL;
1114 }
1115
1116 /* If not found try to load issuer from a suffixed file */
1117 if (!issuer) {
1118 char issuer_path[MAXPATHLEN+1];
1119
1120 in = BIO_new(BIO_s_file());
1121 if (!in)
1122 goto out;
1123
1124 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1125 if (BIO_read_filename(in, issuer_path) <= 0)
1126 goto out;
1127
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001128 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1129 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1130
1131 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001132 if (!xi)
1133 goto out;
1134
1135 if (X509_check_issued(xi, x) != X509_V_OK)
1136 goto out;
1137
1138 issuer = xi;
1139 }
1140
1141 cid = OCSP_cert_to_id(0, x, issuer);
1142 if (!cid)
1143 goto out;
1144
1145 i = i2d_OCSP_CERTID(cid, NULL);
1146 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1147 goto out;
1148
Vincent Bernat02779b62016-04-03 13:48:43 +02001149 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001150 if (!ocsp)
1151 goto out;
1152
1153 p = ocsp->key_data;
1154 i2d_OCSP_CERTID(cid, &p);
1155
1156 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1157 if (iocsp == ocsp)
1158 ocsp = NULL;
1159
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001160#ifndef SSL_CTX_get_tlsext_status_cb
1161# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1162 *cb = (void (*) (void))ctx->tlsext_status_cb;
1163#endif
1164 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1165
1166 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001167 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001168 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001169
1170 cb_arg->is_single = 1;
1171 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001172
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001173 pkey = X509_get_pubkey(x);
1174 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1175 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001176
1177 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1178 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1179 } else {
1180 /*
1181 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1182 * Update that cb_arg with the new cert's staple
1183 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001184 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001185 struct certificate_ocsp *tmp_ocsp;
1186 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001187 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001188 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001189
1190#ifdef SSL_CTX_get_tlsext_status_arg
1191 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1192#else
1193 cb_arg = ctx->tlsext_status_arg;
1194#endif
yanbzhube2774d2015-12-10 15:07:30 -05001195
1196 /*
1197 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1198 * the order of operations below matter, take care when changing it
1199 */
1200 tmp_ocsp = cb_arg->s_ocsp;
1201 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1202 cb_arg->s_ocsp = NULL;
1203 cb_arg->m_ocsp[index] = tmp_ocsp;
1204 cb_arg->is_single = 0;
1205 cb_arg->single_kt = 0;
1206
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001207 pkey = X509_get_pubkey(x);
1208 key_type = EVP_PKEY_base_id(pkey);
1209 EVP_PKEY_free(pkey);
1210
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001211 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001212 if (index >= 0 && !cb_arg->m_ocsp[index])
1213 cb_arg->m_ocsp[index] = iocsp;
1214
1215 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001216
1217 ret = 0;
1218
1219 warn = NULL;
1220 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1221 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001222 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001223 }
1224
1225out:
1226 if (ssl)
1227 SSL_free(ssl);
1228
1229 if (in)
1230 BIO_free(in);
1231
1232 if (xi)
1233 X509_free(xi);
1234
1235 if (cid)
1236 OCSP_CERTID_free(cid);
1237
1238 if (ocsp)
1239 free(ocsp);
1240
1241 if (warn)
1242 free(warn);
1243
1244
1245 return ret;
1246}
1247
1248#endif
1249
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001250#ifdef OPENSSL_IS_BORINGSSL
1251static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1252{
1253 char ocsp_path[MAXPATHLEN+1];
1254 struct stat st;
1255 int fd = -1, r = 0;
1256
1257 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1258 if (stat(ocsp_path, &st))
1259 return 0;
1260
1261 fd = open(ocsp_path, O_RDONLY);
1262 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001263 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001264 return -1;
1265 }
1266
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001267 trash.data = 0;
1268 while (trash.data < trash.size) {
1269 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001270 if (r < 0) {
1271 if (errno == EINTR)
1272 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001273 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001274 close(fd);
1275 return -1;
1276 }
1277 else if (r == 0) {
1278 break;
1279 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001280 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001281 }
1282 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001283 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1284 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001285}
1286#endif
1287
Daniel Jakots54ffb912015-11-06 20:02:41 +01001288#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001289
1290#define CT_EXTENSION_TYPE 18
1291
1292static int sctl_ex_index = -1;
1293
1294/*
1295 * Try to parse Signed Certificate Timestamp List structure. This function
1296 * makes only basic test if the data seems like SCTL. No signature validation
1297 * is performed.
1298 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001299static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001300{
1301 int ret = 1;
1302 int len, pos, sct_len;
1303 unsigned char *data;
1304
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001305 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001306 goto out;
1307
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001308 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001309 len = (data[0] << 8) | data[1];
1310
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001311 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001312 goto out;
1313
1314 data = data + 2;
1315 pos = 0;
1316 while (pos < len) {
1317 if (len - pos < 2)
1318 goto out;
1319
1320 sct_len = (data[pos] << 8) | data[pos + 1];
1321 if (pos + sct_len + 2 > len)
1322 goto out;
1323
1324 pos += sct_len + 2;
1325 }
1326
1327 ret = 0;
1328
1329out:
1330 return ret;
1331}
1332
Willy Tarreau83061a82018-07-13 11:56:34 +02001333static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1334 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001335{
1336 int fd = -1;
1337 int r = 0;
1338 int ret = 1;
1339
1340 *sctl = NULL;
1341
1342 fd = open(sctl_path, O_RDONLY);
1343 if (fd == -1)
1344 goto end;
1345
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001346 trash.data = 0;
1347 while (trash.data < trash.size) {
1348 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001349 if (r < 0) {
1350 if (errno == EINTR)
1351 continue;
1352
1353 goto end;
1354 }
1355 else if (r == 0) {
1356 break;
1357 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001358 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001359 }
1360
1361 ret = ssl_sock_parse_sctl(&trash);
1362 if (ret)
1363 goto end;
1364
Vincent Bernat02779b62016-04-03 13:48:43 +02001365 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001366 if (!chunk_dup(*sctl, &trash)) {
1367 free(*sctl);
1368 *sctl = NULL;
1369 goto end;
1370 }
1371
1372end:
1373 if (fd != -1)
1374 close(fd);
1375
1376 return ret;
1377}
1378
1379int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1380{
Willy Tarreau83061a82018-07-13 11:56:34 +02001381 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001382
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001383 *out = (unsigned char *) sctl->area;
1384 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001385
1386 return 1;
1387}
1388
1389int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1390{
1391 return 1;
1392}
1393
1394static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1395{
1396 char sctl_path[MAXPATHLEN+1];
1397 int ret = -1;
1398 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001399 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001400
1401 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1402
1403 if (stat(sctl_path, &st))
1404 return 1;
1405
1406 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1407 goto out;
1408
1409 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1410 free(sctl);
1411 goto out;
1412 }
1413
1414 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1415
1416 ret = 0;
1417
1418out:
1419 return ret;
1420}
1421
1422#endif
1423
Emeric Brune1f38db2012-09-03 20:36:47 +02001424void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1425{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001426 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001427 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001428 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001429
1430 if (where & SSL_CB_HANDSHAKE_START) {
1431 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001432 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 +02001433 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001434 conn->err_code = CO_ER_SSL_RENEG;
1435 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001436 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001437
1438 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1439 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1440 /* Long certificate chains optimz
1441 If write and read bios are differents, we
1442 consider that the buffering was activated,
1443 so we rise the output buffer size from 4k
1444 to 16k */
1445 write_bio = SSL_get_wbio(ssl);
1446 if (write_bio != SSL_get_rbio(ssl)) {
1447 BIO_set_write_buffer_size(write_bio, 16384);
1448 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1449 }
1450 }
1451 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001452}
1453
Emeric Brune64aef12012-09-21 13:15:06 +02001454/* Callback is called for each certificate of the chain during a verify
1455 ok is set to 1 if preverify detect no error on current certificate.
1456 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001457int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001458{
1459 SSL *ssl;
1460 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001461 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001462
1463 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001464 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001465
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001466 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001467
Emeric Brun81c00f02012-09-21 14:31:21 +02001468 if (ok) /* no errors */
1469 return ok;
1470
1471 depth = X509_STORE_CTX_get_error_depth(x_store);
1472 err = X509_STORE_CTX_get_error(x_store);
1473
1474 /* check if CA error needs to be ignored */
1475 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001476 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1477 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1478 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001479 }
1480
Willy Tarreau07d94e42018-09-20 10:57:52 +02001481 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001482 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001483 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001484 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001485 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001486
Willy Tarreau20879a02012-12-03 16:32:10 +01001487 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001488 return 0;
1489 }
1490
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001491 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1492 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001493
Emeric Brun81c00f02012-09-21 14:31:21 +02001494 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001495 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001496 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001497 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001498 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001499 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001500
Willy Tarreau20879a02012-12-03 16:32:10 +01001501 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001502 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001503}
1504
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001505static inline
1506void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001507 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001508{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001509 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001510 unsigned char *msg;
1511 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001512 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001513
1514 /* This function is called for "from client" and "to server"
1515 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001516 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001517 */
1518
1519 /* "write_p" is set to 0 is the bytes are received messages,
1520 * otherwise it is set to 1.
1521 */
1522 if (write_p != 0)
1523 return;
1524
1525 /* content_type contains the type of message received or sent
1526 * according with the SSL/TLS protocol spec. This message is
1527 * encoded with one byte. The value 256 (two bytes) is used
1528 * for designing the SSL/TLS record layer. According with the
1529 * rfc6101, the expected message (other than 256) are:
1530 * - change_cipher_spec(20)
1531 * - alert(21)
1532 * - handshake(22)
1533 * - application_data(23)
1534 * - (255)
1535 * We are interessed by the handshake and specially the client
1536 * hello.
1537 */
1538 if (content_type != 22)
1539 return;
1540
1541 /* The message length is at least 4 bytes, containing the
1542 * message type and the message length.
1543 */
1544 if (len < 4)
1545 return;
1546
1547 /* First byte of the handshake message id the type of
1548 * message. The konwn types are:
1549 * - hello_request(0)
1550 * - client_hello(1)
1551 * - server_hello(2)
1552 * - certificate(11)
1553 * - server_key_exchange (12)
1554 * - certificate_request(13)
1555 * - server_hello_done(14)
1556 * We are interested by the client hello.
1557 */
1558 msg = (unsigned char *)buf;
1559 if (msg[0] != 1)
1560 return;
1561
1562 /* Next three bytes are the length of the message. The total length
1563 * must be this decoded length + 4. If the length given as argument
1564 * is not the same, we abort the protocol dissector.
1565 */
1566 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1567 if (len < rec_len + 4)
1568 return;
1569 msg += 4;
1570 end = msg + rec_len;
1571 if (end < msg)
1572 return;
1573
1574 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1575 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001576 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1577 */
1578 msg += 1 + 1 + 4 + 28;
1579 if (msg > end)
1580 return;
1581
1582 /* Next, is session id:
1583 * if present, we have to jump by length + 1 for the size information
1584 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001585 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001586 if (msg[0] > 0)
1587 msg += msg[0];
1588 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001589 if (msg > end)
1590 return;
1591
1592 /* Next two bytes are the ciphersuite length. */
1593 if (msg + 2 > end)
1594 return;
1595 rec_len = (msg[0] << 8) + msg[1];
1596 msg += 2;
1597 if (msg + rec_len > end || msg + rec_len < msg)
1598 return;
1599
Willy Tarreaubafbe012017-11-24 17:34:44 +01001600 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001601 if (!capture)
1602 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001603 /* Compute the xxh64 of the ciphersuite. */
1604 capture->xxh64 = XXH64(msg, rec_len, 0);
1605
1606 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001607 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1608 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001609 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001610
1611 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001612}
1613
Emeric Brun29f037d2014-04-25 19:05:36 +02001614/* Callback is called for ssl protocol analyse */
1615void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1616{
Emeric Brun29f037d2014-04-25 19:05:36 +02001617#ifdef TLS1_RT_HEARTBEAT
1618 /* test heartbeat received (write_p is set to 0
1619 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001620 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001621 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001622 const unsigned char *p = buf;
1623 unsigned int payload;
1624
Emeric Brun29f037d2014-04-25 19:05:36 +02001625 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001626
1627 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1628 if (*p != TLS1_HB_REQUEST)
1629 return;
1630
Willy Tarreauaeed6722014-04-25 23:59:58 +02001631 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001632 goto kill_it;
1633
1634 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001635 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001636 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001637 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001638 /* We have a clear heartbleed attack (CVE-2014-0160), the
1639 * advertised payload is larger than the advertised packet
1640 * length, so we have garbage in the buffer between the
1641 * payload and the end of the buffer (p+len). We can't know
1642 * if the SSL stack is patched, and we don't know if we can
1643 * safely wipe out the area between p+3+len and payload.
1644 * So instead, we prevent the response from being sent by
1645 * setting the max_send_fragment to 0 and we report an SSL
1646 * error, which will kill this connection. It will be reported
1647 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001648 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1649 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001650 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001651 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1652 return;
1653 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001654#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001655 if (global_ssl.capture_cipherlist > 0)
1656 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001657}
1658
Bernard Spil13c53f82018-02-15 13:34:58 +01001659#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001660static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1661 const unsigned char *in, unsigned int inlen,
1662 void *arg)
1663{
1664 struct server *srv = arg;
1665
1666 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1667 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1668 return SSL_TLSEXT_ERR_OK;
1669 return SSL_TLSEXT_ERR_NOACK;
1670}
1671#endif
1672
1673#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001674/* This callback is used so that the server advertises the list of
1675 * negociable protocols for NPN.
1676 */
1677static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1678 unsigned int *len, void *arg)
1679{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001680 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001681
1682 *data = (const unsigned char *)conf->npn_str;
1683 *len = conf->npn_len;
1684 return SSL_TLSEXT_ERR_OK;
1685}
1686#endif
1687
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001688#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001689/* This callback is used so that the server advertises the list of
1690 * negociable protocols for ALPN.
1691 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001692static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1693 unsigned char *outlen,
1694 const unsigned char *server,
1695 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001696{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001697 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001698
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001699 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1700 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1701 return SSL_TLSEXT_ERR_NOACK;
1702 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001703 return SSL_TLSEXT_ERR_OK;
1704}
1705#endif
1706
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001707#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001708#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001709
Christopher Faulet30548802015-06-11 13:39:32 +02001710/* Create a X509 certificate with the specified servername and serial. This
1711 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001712static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001713ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001714{
Christopher Faulet7969a332015-10-09 11:15:03 +02001715 X509 *cacert = bind_conf->ca_sign_cert;
1716 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001717 SSL_CTX *ssl_ctx = NULL;
1718 X509 *newcrt = NULL;
1719 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001720 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001721 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001722 X509_NAME *name;
1723 const EVP_MD *digest;
1724 X509V3_CTX ctx;
1725 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001726 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001727
Christopher Faulet48a83322017-07-28 16:56:09 +02001728 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001729#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1730 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1731#else
1732 tmp_ssl = SSL_new(bind_conf->default_ctx);
1733 if (tmp_ssl)
1734 pkey = SSL_get_privatekey(tmp_ssl);
1735#endif
1736 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001737 goto mkcert_error;
1738
1739 /* Create the certificate */
1740 if (!(newcrt = X509_new()))
1741 goto mkcert_error;
1742
1743 /* Set version number for the certificate (X509v3) and the serial
1744 * number */
1745 if (X509_set_version(newcrt, 2L) != 1)
1746 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001747 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001748
1749 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001750 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1751 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001752 goto mkcert_error;
1753
1754 /* set public key in the certificate */
1755 if (X509_set_pubkey(newcrt, pkey) != 1)
1756 goto mkcert_error;
1757
1758 /* Set issuer name from the CA */
1759 if (!(name = X509_get_subject_name(cacert)))
1760 goto mkcert_error;
1761 if (X509_set_issuer_name(newcrt, name) != 1)
1762 goto mkcert_error;
1763
1764 /* Set the subject name using the same, but the CN */
1765 name = X509_NAME_dup(name);
1766 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1767 (const unsigned char *)servername,
1768 -1, -1, 0) != 1) {
1769 X509_NAME_free(name);
1770 goto mkcert_error;
1771 }
1772 if (X509_set_subject_name(newcrt, name) != 1) {
1773 X509_NAME_free(name);
1774 goto mkcert_error;
1775 }
1776 X509_NAME_free(name);
1777
1778 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001779 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1781 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1782 X509_EXTENSION *ext;
1783
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001784 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001785 goto mkcert_error;
1786 if (!X509_add_ext(newcrt, ext, -1)) {
1787 X509_EXTENSION_free(ext);
1788 goto mkcert_error;
1789 }
1790 X509_EXTENSION_free(ext);
1791 }
1792
1793 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001794
1795 key_type = EVP_PKEY_base_id(capkey);
1796
1797 if (key_type == EVP_PKEY_DSA)
1798 digest = EVP_sha1();
1799 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001800 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001801 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001802 digest = EVP_sha256();
1803 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001804#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001805 int nid;
1806
1807 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1808 goto mkcert_error;
1809 if (!(digest = EVP_get_digestbynid(nid)))
1810 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001811#else
1812 goto mkcert_error;
1813#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001814 }
1815
Christopher Faulet31af49d2015-06-09 17:29:50 +02001816 if (!(X509_sign(newcrt, capkey, digest)))
1817 goto mkcert_error;
1818
1819 /* Create and set the new SSL_CTX */
1820 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1821 goto mkcert_error;
1822 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1823 goto mkcert_error;
1824 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1825 goto mkcert_error;
1826 if (!SSL_CTX_check_private_key(ssl_ctx))
1827 goto mkcert_error;
1828
1829 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001830
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001831#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001832 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001833#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001834#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1835 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001836 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001837 EC_KEY *ecc;
1838 int nid;
1839
1840 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1841 goto end;
1842 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1843 goto end;
1844 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1845 EC_KEY_free(ecc);
1846 }
1847#endif
1848 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001849 return ssl_ctx;
1850
1851 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001852 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001853 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001854 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1855 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856 return NULL;
1857}
1858
Christopher Faulet7969a332015-10-09 11:15:03 +02001859SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001860ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001861{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001862 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001863
1864 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001865}
1866
Christopher Faulet30548802015-06-11 13:39:32 +02001867/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001868 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001869SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001870ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001871{
1872 struct lru64 *lru = NULL;
1873
1874 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001875 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001876 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001877 if (lru && lru->domain) {
1878 if (ssl)
1879 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001880 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001881 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001882 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001883 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001884 }
1885 return NULL;
1886}
1887
Emeric Brun821bb9b2017-06-15 16:37:39 +02001888/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1889 * function is not thread-safe, it should only be used to check if a certificate
1890 * exists in the lru cache (with no warranty it will not be removed by another
1891 * thread). It is kept for backward compatibility. */
1892SSL_CTX *
1893ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1894{
1895 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1896}
1897
Christopher Fauletd2cab922015-07-28 16:03:47 +02001898/* Set a certificate int the LRU cache used to store generated
1899 * certificate. Return 0 on success, otherwise -1 */
1900int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001901ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001902{
1903 struct lru64 *lru = NULL;
1904
1905 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001906 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001907 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001908 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001909 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001910 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001911 }
Christopher Faulet30548802015-06-11 13:39:32 +02001912 if (lru->domain && lru->data)
1913 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001914 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001915 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001916 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001917 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001918 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001919}
1920
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001921/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001922unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001923ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001924{
1925 return XXH32(data, len, ssl_ctx_lru_seed);
1926}
1927
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001928/* Generate a cert and immediately assign it to the SSL session so that the cert's
1929 * refcount is maintained regardless of the cert's presence in the LRU cache.
1930 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001931static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001932ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001933{
1934 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001935 SSL_CTX *ssl_ctx = NULL;
1936 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001937 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001938
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001939 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001940 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001941 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001942 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001943 if (lru && lru->domain)
1944 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001945 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001946 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001947 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001948 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001949 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001950 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001951 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001952 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001953 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001954 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001955 SSL_set_SSL_CTX(ssl, ssl_ctx);
1956 /* No LRU cache, this CTX will be released as soon as the session dies */
1957 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001958 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001959 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001960 return 0;
1961}
1962static int
1963ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1964{
1965 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001966 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001967
1968 conn_get_to_addr(conn);
1969 if (conn->flags & CO_FL_ADDR_TO_SET) {
1970 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001971 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001972 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001973 }
1974 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001975}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001976#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001977
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001978
1979#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1980#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1981#endif
1982
1983#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1984#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1985#define SSL_renegotiate_pending(arg) 0
1986#endif
1987#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1988#define SSL_OP_SINGLE_ECDH_USE 0
1989#endif
1990#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1991#define SSL_OP_NO_TICKET 0
1992#endif
1993#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1994#define SSL_OP_NO_COMPRESSION 0
1995#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001996#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1997#undef SSL_OP_NO_SSLv3
1998#define SSL_OP_NO_SSLv3 0
1999#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002000#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
2001#define SSL_OP_NO_TLSv1_1 0
2002#endif
2003#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
2004#define SSL_OP_NO_TLSv1_2 0
2005#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002006#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002007#define SSL_OP_NO_TLSv1_3 0
2008#endif
2009#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
2010#define SSL_OP_SINGLE_DH_USE 0
2011#endif
2012#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
2013#define SSL_OP_SINGLE_ECDH_USE 0
2014#endif
2015#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
2016#define SSL_MODE_RELEASE_BUFFERS 0
2017#endif
2018#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
2019#define SSL_MODE_SMALL_BUFFERS 0
2020#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02002021#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2022#define SSL_OP_PRIORITIZE_CHACHA 0
2023#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002024
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002025#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2027
2028static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002030#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002031 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002032 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2033#endif
2034}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2036 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002037 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2038}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002039static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002040#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002041 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002042 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2043#endif
2044}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002045static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002046#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002047 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002048 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2049#endif
2050}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002051/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002052static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2053/* Unusable in this context. */
2054static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2055static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2056static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2057static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2058static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002059#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060typedef enum { SET_MIN, SET_MAX } set_context_func;
2061
2062static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2063 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002064 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2065}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002066static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2067 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2068 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2069}
2070static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2071 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002072 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2073}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002074static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2075 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2076 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2077}
2078static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2079 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002080 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2081}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002082static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2083 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2084 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2085}
2086static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2087 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002088 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2089}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002090static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2091 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2092 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2093}
2094static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002095#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002096 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002097 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2098#endif
2099}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002100static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2101#if SSL_OP_NO_TLSv1_3
2102 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2103 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002104#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002105}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002106#endif
2107static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2108static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002109
2110static struct {
2111 int option;
2112 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002113 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2114 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002115 const char *name;
2116} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002117 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2118 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2119 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2120 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2121 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2122 {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 +02002123};
2124
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002125static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2126{
2127 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2128 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2129 SSL_set_SSL_CTX(ssl, ctx);
2130}
2131
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002132#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002133
2134static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2135{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002136 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002137 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002138
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002139 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2140 return SSL_TLSEXT_ERR_OK;
2141 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002142}
2143
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002144#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002145static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2146{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002147 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002148#else
2149static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2150{
2151#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002152 struct connection *conn;
2153 struct bind_conf *s;
2154 const uint8_t *extension_data;
2155 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002156 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002157
2158 char *wildp = NULL;
2159 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002160 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002161 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002162 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002163 int i;
2164
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002165 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002166 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002167
Olivier Houchard9679ac92017-10-27 14:58:08 +02002168 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002169 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002170#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002171 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2172 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002173#else
2174 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2175#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002176 /*
2177 * The server_name extension was given too much extensibility when it
2178 * was written, so parsing the normal case is a bit complex.
2179 */
2180 size_t len;
2181 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002182 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002183 /* Extract the length of the supplied list of names. */
2184 len = (*extension_data++) << 8;
2185 len |= *extension_data++;
2186 if (len + 2 != extension_len)
2187 goto abort;
2188 /*
2189 * The list in practice only has a single element, so we only consider
2190 * the first one.
2191 */
2192 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2193 goto abort;
2194 extension_len = len - 1;
2195 /* Now we can finally pull out the byte array with the actual hostname. */
2196 if (extension_len <= 2)
2197 goto abort;
2198 len = (*extension_data++) << 8;
2199 len |= *extension_data++;
2200 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2201 || memchr(extension_data, 0, len) != NULL)
2202 goto abort;
2203 servername = extension_data;
2204 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002206#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2207 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002208 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002209 }
2210#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002211 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002212 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002213 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002214 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002215 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002216 goto abort;
2217 }
2218
2219 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002220#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002222#else
2223 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2224#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002225 uint8_t sign;
2226 size_t len;
2227 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002229 len = (*extension_data++) << 8;
2230 len |= *extension_data++;
2231 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002232 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002233 if (len % 2 != 0)
2234 goto abort;
2235 for (; len > 0; len -= 2) {
2236 extension_data++; /* hash */
2237 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002238 switch (sign) {
2239 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002240 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002241 break;
2242 case TLSEXT_signature_ecdsa:
2243 has_ecdsa_sig = 1;
2244 break;
2245 default:
2246 continue;
2247 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002248 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002249 break;
2250 }
2251 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002252 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002253 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002254 }
2255 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002256 const SSL_CIPHER *cipher;
2257 size_t len;
2258 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002259 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002260#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002261 len = ctx->cipher_suites_len;
2262 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002263#else
2264 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2265#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002266 if (len % 2 != 0)
2267 goto abort;
2268 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002269#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002270 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002271 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002272#else
2273 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2274#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002275 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002276 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 break;
2278 }
2279 }
2280 }
2281
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002282 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002283 trash.area[i] = tolower(servername[i]);
2284 if (!wildp && (trash.area[i] == '.'))
2285 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002286 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002287 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002288
2289 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002290 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002291
2292 /* lookup a not neg filter */
2293 for (n = node; n; n = ebmb_next_dup(n)) {
2294 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002295 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002297 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 break;
2300 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002301 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002302 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002303 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002304 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 if (!node_anonymous)
2306 node_anonymous = n;
2307 break;
2308 }
2309 }
2310 }
2311 if (wildp) {
2312 /* lookup in wildcards names */
2313 node = ebst_lookup(&s->sni_w_ctx, wildp);
2314 for (n = node; n; n = ebmb_next_dup(n)) {
2315 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002316 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002318 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002320 break;
2321 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002322 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002323 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002325 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002326 if (!node_anonymous)
2327 node_anonymous = n;
2328 break;
2329 }
2330 }
2331 }
2332 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002333 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002334 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2335 : ((has_rsa_sig && node_rsa) ? node_rsa
2336 : (node_anonymous ? node_anonymous
2337 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2338 : node_rsa /* no rsa signature case (far far away) */
2339 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002340 if (node) {
2341 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002342 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002343 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002344 if (conf) {
2345 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2346 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2347 if (conf->early_data)
2348 allow_early = 1;
2349 }
2350 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002351 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002352#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002353 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002354 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002355 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002356 }
2357#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002358 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002360 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002361 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002362allow_early:
2363#ifdef OPENSSL_IS_BORINGSSL
2364 if (allow_early)
2365 SSL_set_early_data_enabled(ssl, 1);
2366#else
2367 if (!allow_early)
2368 SSL_set_max_early_data(ssl, 0);
2369#endif
2370 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002371 abort:
2372 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2373 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002374#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002375 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002376#else
2377 *al = SSL_AD_UNRECOGNIZED_NAME;
2378 return 0;
2379#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002380}
2381
2382#else /* OPENSSL_IS_BORINGSSL */
2383
Emeric Brunfc0421f2012-09-07 17:30:07 +02002384/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2385 * warning when no match is found, which implies the default (first) cert
2386 * will keep being used.
2387 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002388static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002389{
2390 const char *servername;
2391 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002392 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002393 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002394 int i;
2395 (void)al; /* shut gcc stupid warning */
2396
2397 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002398 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002399#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002400 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2401 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002402#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002403 if (s->strict_sni)
2404 return SSL_TLSEXT_ERR_ALERT_FATAL;
2405 ssl_sock_switchctx_set(ssl, s->default_ctx);
2406 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002407 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002408
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002409 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002410 if (!servername[i])
2411 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002412 trash.area[i] = tolower(servername[i]);
2413 if (!wildp && (trash.area[i] == '.'))
2414 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002415 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002416 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002417
2418 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002419 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002420
2421 /* lookup a not neg filter */
2422 for (n = node; n; n = ebmb_next_dup(n)) {
2423 if (!container_of(n, struct sni_ctx, name)->neg) {
2424 node = n;
2425 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002426 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002427 }
2428 if (!node && wildp) {
2429 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002430 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002431 }
2432 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002433#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002434 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2435 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002436 return SSL_TLSEXT_ERR_OK;
2437 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002438#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002439 if (s->strict_sni)
2440 return SSL_TLSEXT_ERR_ALERT_FATAL;
2441 ssl_sock_switchctx_set(ssl, s->default_ctx);
2442 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002443 }
2444
2445 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002446 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002447 return SSL_TLSEXT_ERR_OK;
2448}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002449#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002450#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2451
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002452#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002453
2454static DH * ssl_get_dh_1024(void)
2455{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002456 static unsigned char dh1024_p[]={
2457 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2458 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2459 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2460 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2461 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2462 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2463 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2464 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2465 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2466 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2467 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2468 };
2469 static unsigned char dh1024_g[]={
2470 0x02,
2471 };
2472
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002473 BIGNUM *p;
2474 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002475 DH *dh = DH_new();
2476 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002477 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2478 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002479
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002480 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002481 DH_free(dh);
2482 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002483 } else {
2484 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002485 }
2486 }
2487 return dh;
2488}
2489
2490static DH *ssl_get_dh_2048(void)
2491{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002492 static unsigned char dh2048_p[]={
2493 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2494 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2495 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2496 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2497 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2498 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2499 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2500 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2501 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2502 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2503 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2504 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2505 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2506 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2507 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2508 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2509 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2510 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2511 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2512 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2513 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2514 0xB7,0x1F,0x77,0xF3,
2515 };
2516 static unsigned char dh2048_g[]={
2517 0x02,
2518 };
2519
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002520 BIGNUM *p;
2521 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002522 DH *dh = DH_new();
2523 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002524 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2525 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002526
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002527 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002528 DH_free(dh);
2529 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002530 } else {
2531 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002532 }
2533 }
2534 return dh;
2535}
2536
2537static DH *ssl_get_dh_4096(void)
2538{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002539 static unsigned char dh4096_p[]={
2540 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2541 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2542 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2543 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2544 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2545 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2546 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2547 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2548 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2549 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2550 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2551 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2552 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2553 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2554 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2555 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2556 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2557 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2558 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2559 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2560 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2561 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2562 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2563 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2564 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2565 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2566 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2567 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2568 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2569 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2570 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2571 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2572 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2573 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2574 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2575 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2576 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2577 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2578 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2579 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2580 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2581 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2582 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002583 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002584 static unsigned char dh4096_g[]={
2585 0x02,
2586 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002587
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002588 BIGNUM *p;
2589 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002590 DH *dh = DH_new();
2591 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002592 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2593 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002594
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002595 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002596 DH_free(dh);
2597 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002598 } else {
2599 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002600 }
2601 }
2602 return dh;
2603}
2604
2605/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002606 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002607static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2608{
2609 DH *dh = NULL;
2610 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002611 int type;
2612
2613 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002614
2615 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2616 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2617 */
2618 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2619 keylen = EVP_PKEY_bits(pkey);
2620 }
2621
Willy Tarreauef934602016-12-22 23:12:01 +01002622 if (keylen > global_ssl.default_dh_param) {
2623 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002624 }
2625
Remi Gacogned3a341a2015-05-29 16:26:17 +02002626 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002627 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002628 }
2629 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002630 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002631 }
2632 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002633 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002634 }
2635
2636 return dh;
2637}
2638
Remi Gacogne47783ef2015-05-29 15:53:22 +02002639static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002640{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002641 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002642 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002643
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002644 if (in == NULL)
2645 goto end;
2646
Remi Gacogne47783ef2015-05-29 15:53:22 +02002647 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002648 goto end;
2649
Remi Gacogne47783ef2015-05-29 15:53:22 +02002650 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2651
2652end:
2653 if (in)
2654 BIO_free(in);
2655
Emeric Brune1b4ed42018-08-16 15:14:12 +02002656 ERR_clear_error();
2657
Remi Gacogne47783ef2015-05-29 15:53:22 +02002658 return dh;
2659}
2660
2661int ssl_sock_load_global_dh_param_from_file(const char *filename)
2662{
2663 global_dh = ssl_sock_get_dh_from_file(filename);
2664
2665 if (global_dh) {
2666 return 0;
2667 }
2668
2669 return -1;
2670}
2671
2672/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002673 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002674int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2675{
2676 int ret = -1;
2677 DH *dh = ssl_sock_get_dh_from_file(file);
2678
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002679 if (dh) {
2680 ret = 1;
2681 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002682
2683 if (ssl_dh_ptr_index >= 0) {
2684 /* store a pointer to the DH params to avoid complaining about
2685 ssl-default-dh-param not being set for this SSL_CTX */
2686 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2687 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002688 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002689 else if (global_dh) {
2690 SSL_CTX_set_tmp_dh(ctx, global_dh);
2691 ret = 0; /* DH params not found */
2692 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002693 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002694 /* Clear openssl global errors stack */
2695 ERR_clear_error();
2696
Willy Tarreauef934602016-12-22 23:12:01 +01002697 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002698 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002699 if (local_dh_1024 == NULL)
2700 local_dh_1024 = ssl_get_dh_1024();
2701
Remi Gacogne8de54152014-07-15 11:36:40 +02002702 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002703 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002704
Remi Gacogne8de54152014-07-15 11:36:40 +02002705 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002706 }
2707 else {
2708 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2709 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002710
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002711 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002712 }
Emeric Brun644cde02012-12-14 11:21:13 +01002713
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002714end:
2715 if (dh)
2716 DH_free(dh);
2717
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002718 return ret;
2719}
2720#endif
2721
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002722static 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 +02002723 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002724{
2725 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002726 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002727 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002728
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002729 if (*name == '!') {
2730 neg = 1;
2731 name++;
2732 }
2733 if (*name == '*') {
2734 wild = 1;
2735 name++;
2736 }
2737 /* !* filter is a nop */
2738 if (neg && wild)
2739 return order;
2740 if (*name) {
2741 int j, len;
2742 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002743 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002744 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002745 if (j >= trash.size)
2746 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002747 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002748
2749 /* Check for duplicates. */
2750 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002751 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002752 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002753 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002754 for (; node; node = ebmb_next_dup(node)) {
2755 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002756 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002757 return order;
2758 }
2759
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002760 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002761 if (!sc)
2762 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002763 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002764 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002765 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002766 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002767 sc->order = order++;
2768 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002769 if (kinfo.sig != TLSEXT_signature_anonymous)
2770 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002771 if (wild)
2772 ebst_insert(&s->sni_w_ctx, &sc->name);
2773 else
2774 ebst_insert(&s->sni_ctx, &sc->name);
2775 }
2776 return order;
2777}
2778
yanbzhu488a4d22015-12-01 15:16:07 -05002779
2780/* The following code is used for loading multiple crt files into
2781 * SSL_CTX's based on CN/SAN
2782 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002783#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002784/* This is used to preload the certifcate, private key
2785 * and Cert Chain of a file passed in via the crt
2786 * argument
2787 *
2788 * This way, we do not have to read the file multiple times
2789 */
2790struct cert_key_and_chain {
2791 X509 *cert;
2792 EVP_PKEY *key;
2793 unsigned int num_chain_certs;
2794 /* This is an array of X509 pointers */
2795 X509 **chain_certs;
2796};
2797
yanbzhu08ce6ab2015-12-02 13:01:29 -05002798#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2799
2800struct key_combo_ctx {
2801 SSL_CTX *ctx;
2802 int order;
2803};
2804
2805/* Map used for processing multiple keypairs for a single purpose
2806 *
2807 * This maps CN/SNI name to certificate type
2808 */
2809struct sni_keytype {
2810 int keytypes; /* BITMASK for keytypes */
2811 struct ebmb_node name; /* node holding the servername value */
2812};
2813
2814
yanbzhu488a4d22015-12-01 15:16:07 -05002815/* Frees the contents of a cert_key_and_chain
2816 */
2817static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2818{
2819 int i;
2820
2821 if (!ckch)
2822 return;
2823
2824 /* Free the certificate and set pointer to NULL */
2825 if (ckch->cert)
2826 X509_free(ckch->cert);
2827 ckch->cert = NULL;
2828
2829 /* Free the key and set pointer to NULL */
2830 if (ckch->key)
2831 EVP_PKEY_free(ckch->key);
2832 ckch->key = NULL;
2833
2834 /* Free each certificate in the chain */
2835 for (i = 0; i < ckch->num_chain_certs; i++) {
2836 if (ckch->chain_certs[i])
2837 X509_free(ckch->chain_certs[i]);
2838 }
2839
2840 /* Free the chain obj itself and set to NULL */
2841 if (ckch->num_chain_certs > 0) {
2842 free(ckch->chain_certs);
2843 ckch->num_chain_certs = 0;
2844 ckch->chain_certs = NULL;
2845 }
2846
2847}
2848
2849/* checks if a key and cert exists in the ckch
2850 */
2851static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2852{
2853 return (ckch->cert != NULL && ckch->key != NULL);
2854}
2855
2856
2857/* Loads the contents of a crt file (path) into a cert_key_and_chain
2858 * This allows us to carry the contents of the file without having to
2859 * read the file multiple times.
2860 *
2861 * returns:
2862 * 0 on Success
2863 * 1 on SSL Failure
2864 * 2 on file not found
2865 */
2866static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2867{
2868
2869 BIO *in;
2870 X509 *ca = NULL;
2871 int ret = 1;
2872
2873 ssl_sock_free_cert_key_and_chain_contents(ckch);
2874
2875 in = BIO_new(BIO_s_file());
2876 if (in == NULL)
2877 goto end;
2878
2879 if (BIO_read_filename(in, path) <= 0)
2880 goto end;
2881
yanbzhu488a4d22015-12-01 15:16:07 -05002882 /* Read Private Key */
2883 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2884 if (ckch->key == NULL) {
2885 memprintf(err, "%sunable to load private key from file '%s'.\n",
2886 err && *err ? *err : "", path);
2887 goto end;
2888 }
2889
Willy Tarreaubb137a82016-04-06 19:02:38 +02002890 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002891 if (BIO_reset(in) == -1) {
2892 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2893 err && *err ? *err : "", path);
2894 goto end;
2895 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002896
2897 /* Read Certificate */
2898 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2899 if (ckch->cert == NULL) {
2900 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2901 err && *err ? *err : "", path);
2902 goto end;
2903 }
2904
yanbzhu488a4d22015-12-01 15:16:07 -05002905 /* Read Certificate Chain */
2906 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2907 /* Grow the chain certs */
2908 ckch->num_chain_certs++;
2909 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2910
2911 /* use - 1 here since we just incremented it above */
2912 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2913 }
2914 ret = ERR_get_error();
2915 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2916 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2917 err && *err ? *err : "", path);
2918 ret = 1;
2919 goto end;
2920 }
2921
2922 ret = 0;
2923
2924end:
2925
2926 ERR_clear_error();
2927 if (in)
2928 BIO_free(in);
2929
2930 /* Something went wrong in one of the reads */
2931 if (ret != 0)
2932 ssl_sock_free_cert_key_and_chain_contents(ckch);
2933
2934 return ret;
2935}
2936
2937/* Loads the info in ckch into ctx
2938 * Currently, this does not process any information about ocsp, dhparams or
2939 * sctl
2940 * Returns
2941 * 0 on success
2942 * 1 on failure
2943 */
2944static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2945{
2946 int i = 0;
2947
2948 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2949 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2950 err && *err ? *err : "", path);
2951 return 1;
2952 }
2953
2954 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2955 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2956 err && *err ? *err : "", path);
2957 return 1;
2958 }
2959
yanbzhu488a4d22015-12-01 15:16:07 -05002960 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2961 for (i = 0; i < ckch->num_chain_certs; i++) {
2962 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002963 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2964 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002965 return 1;
2966 }
2967 }
2968
2969 if (SSL_CTX_check_private_key(ctx) <= 0) {
2970 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2971 err && *err ? *err : "", path);
2972 return 1;
2973 }
2974
2975 return 0;
2976}
2977
yanbzhu08ce6ab2015-12-02 13:01:29 -05002978
2979static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2980{
2981 struct sni_keytype *s_kt = NULL;
2982 struct ebmb_node *node;
2983 int i;
2984
2985 for (i = 0; i < trash.size; i++) {
2986 if (!str[i])
2987 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002988 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002989 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002990 trash.area[i] = 0;
2991 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002992 if (!node) {
2993 /* CN not found in tree */
2994 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2995 /* Using memcpy here instead of strncpy.
2996 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2997 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2998 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002999 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003000 s_kt->keytypes = 0;
3001 ebst_insert(sni_keytypes, &s_kt->name);
3002 } else {
3003 /* CN found in tree */
3004 s_kt = container_of(node, struct sni_keytype, name);
3005 }
3006
3007 /* Mark that this CN has the keytype of key_index via keytypes mask */
3008 s_kt->keytypes |= 1<<key_index;
3009
3010}
3011
3012
3013/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3014 * If any are found, group these files into a set of SSL_CTX*
3015 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3016 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003017 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003018 *
3019 * Returns
3020 * 0 on success
3021 * 1 on failure
3022 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003023static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3024 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003025{
3026 char fp[MAXPATHLEN+1] = {0};
3027 int n = 0;
3028 int i = 0;
3029 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3030 struct eb_root sni_keytypes_map = { {0} };
3031 struct ebmb_node *node;
3032 struct ebmb_node *next;
3033 /* Array of SSL_CTX pointers corresponding to each possible combo
3034 * of keytypes
3035 */
3036 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3037 int rv = 0;
3038 X509_NAME *xname = NULL;
3039 char *str = NULL;
3040#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3041 STACK_OF(GENERAL_NAME) *names = NULL;
3042#endif
3043
3044 /* Load all possible certs and keys */
3045 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3046 struct stat buf;
3047
3048 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3049 if (stat(fp, &buf) == 0) {
3050 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3051 rv = 1;
3052 goto end;
3053 }
3054 }
3055 }
3056
3057 /* Process each ckch and update keytypes for each CN/SAN
3058 * for example, if CN/SAN www.a.com is associated with
3059 * certs with keytype 0 and 2, then at the end of the loop,
3060 * www.a.com will have:
3061 * keyindex = 0 | 1 | 4 = 5
3062 */
3063 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3064
3065 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3066 continue;
3067
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003068 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003069 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003070 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3071 } else {
3072 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3073 * so the line that contains logic is marked via comments
3074 */
3075 xname = X509_get_subject_name(certs_and_keys[n].cert);
3076 i = -1;
3077 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3078 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003079 ASN1_STRING *value;
3080 value = X509_NAME_ENTRY_get_data(entry);
3081 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003082 /* Important line is here */
3083 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003085 OPENSSL_free(str);
3086 str = NULL;
3087 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003088 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003089
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003090 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003091#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003092 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3093 if (names) {
3094 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3095 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003096
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003097 if (name->type == GEN_DNS) {
3098 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3099 /* Important line is here */
3100 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003101
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003102 OPENSSL_free(str);
3103 str = NULL;
3104 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003105 }
3106 }
3107 }
3108 }
3109#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3110 }
3111
3112 /* If no files found, return error */
3113 if (eb_is_empty(&sni_keytypes_map)) {
3114 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3115 err && *err ? *err : "", path);
3116 rv = 1;
3117 goto end;
3118 }
3119
3120 /* We now have a map of CN/SAN to keytypes that are loaded in
3121 * Iterate through the map to create the SSL_CTX's (if needed)
3122 * and add each CTX to the SNI tree
3123 *
3124 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003125 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003126 * combination is denoted by the key in the map. Each key
3127 * has a value between 1 and 2^n - 1. Conveniently, the array
3128 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3129 * entry in the array to correspond to the unique combo (key)
3130 * associated with i. This unique key combo (i) will be associated
3131 * with combos[i-1]
3132 */
3133
3134 node = ebmb_first(&sni_keytypes_map);
3135 while (node) {
3136 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003137 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003138 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003139
3140 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3141 i = container_of(node, struct sni_keytype, name)->keytypes;
3142 cur_ctx = key_combos[i-1].ctx;
3143
3144 if (cur_ctx == NULL) {
3145 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003146 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003147 if (cur_ctx == NULL) {
3148 memprintf(err, "%sunable to allocate SSL context.\n",
3149 err && *err ? *err : "");
3150 rv = 1;
3151 goto end;
3152 }
3153
yanbzhube2774d2015-12-10 15:07:30 -05003154 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003155 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3156 if (i & (1<<n)) {
3157 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003158 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3159 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003160 SSL_CTX_free(cur_ctx);
3161 rv = 1;
3162 goto end;
3163 }
yanbzhube2774d2015-12-10 15:07:30 -05003164
3165#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3166 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003167 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003168 if (err)
3169 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 +00003170 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003171 SSL_CTX_free(cur_ctx);
3172 rv = 1;
3173 goto end;
3174 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003175#elif (defined OPENSSL_IS_BORINGSSL)
3176 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003177#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003178 }
3179 }
3180
3181 /* Load DH params into the ctx to support DHE keys */
3182#ifndef OPENSSL_NO_DH
3183 if (ssl_dh_ptr_index >= 0)
3184 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3185
3186 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3187 if (rv < 0) {
3188 if (err)
3189 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3190 *err ? *err : "", path);
3191 rv = 1;
3192 goto end;
3193 }
3194#endif
3195
3196 /* Update key_combos */
3197 key_combos[i-1].ctx = cur_ctx;
3198 }
3199
3200 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003201 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003202 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003203 node = ebmb_next(node);
3204 }
3205
3206
3207 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3208 if (!bind_conf->default_ctx) {
3209 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3210 if (key_combos[i].ctx) {
3211 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003212 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003213 break;
3214 }
3215 }
3216 }
3217
3218end:
3219
3220 if (names)
3221 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3222
3223 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3224 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3225
3226 node = ebmb_first(&sni_keytypes_map);
3227 while (node) {
3228 next = ebmb_next(node);
3229 ebmb_delete(node);
3230 node = next;
3231 }
3232
3233 return rv;
3234}
3235#else
3236/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003237static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3238 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003239{
3240 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3241 err && *err ? *err : "", path, strerror(errno));
3242 return 1;
3243}
3244
yanbzhu488a4d22015-12-01 15:16:07 -05003245#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3246
Emeric Brunfc0421f2012-09-07 17:30:07 +02003247/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3248 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3249 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003250static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3251 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003252{
3253 BIO *in;
3254 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003255 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003256 int ret = -1;
3257 int order = 0;
3258 X509_NAME *xname;
3259 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003260 pem_password_cb *passwd_cb;
3261 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003262 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003263 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264
Emeric Brunfc0421f2012-09-07 17:30:07 +02003265#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3266 STACK_OF(GENERAL_NAME) *names;
3267#endif
3268
3269 in = BIO_new(BIO_s_file());
3270 if (in == NULL)
3271 goto end;
3272
3273 if (BIO_read_filename(in, file) <= 0)
3274 goto end;
3275
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003276
3277 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3278 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3279
3280 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003281 if (x == NULL)
3282 goto end;
3283
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003284 pkey = X509_get_pubkey(x);
3285 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003286 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003287 switch(EVP_PKEY_base_id(pkey)) {
3288 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003289 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003290 break;
3291 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003292 kinfo.sig = TLSEXT_signature_ecdsa;
3293 break;
3294 case EVP_PKEY_DSA:
3295 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003296 break;
3297 }
3298 EVP_PKEY_free(pkey);
3299 }
3300
Emeric Brun50bcecc2013-04-22 13:05:23 +02003301 if (fcount) {
3302 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003303 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003304 }
3305 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003306#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003307 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3308 if (names) {
3309 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3310 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3311 if (name->type == GEN_DNS) {
3312 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003313 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003314 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003315 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003316 }
3317 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003318 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003319 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003320#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003321 xname = X509_get_subject_name(x);
3322 i = -1;
3323 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3324 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003325 ASN1_STRING *value;
3326
3327 value = X509_NAME_ENTRY_get_data(entry);
3328 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003329 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003330 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003331 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003332 }
3333 }
3334
3335 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3336 if (!SSL_CTX_use_certificate(ctx, x))
3337 goto end;
3338
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003339#ifdef SSL_CTX_clear_extra_chain_certs
3340 SSL_CTX_clear_extra_chain_certs(ctx);
3341#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003342 if (ctx->extra_certs != NULL) {
3343 sk_X509_pop_free(ctx->extra_certs, X509_free);
3344 ctx->extra_certs = NULL;
3345 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003346#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003347
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003348 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003349 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3350 X509_free(ca);
3351 goto end;
3352 }
3353 }
3354
3355 err = ERR_get_error();
3356 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3357 /* we successfully reached the last cert in the file */
3358 ret = 1;
3359 }
3360 ERR_clear_error();
3361
3362end:
3363 if (x)
3364 X509_free(x);
3365
3366 if (in)
3367 BIO_free(in);
3368
3369 return ret;
3370}
3371
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003372static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3373 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003374{
3375 int ret;
3376 SSL_CTX *ctx;
3377
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003378 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003379 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003380 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3381 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003382 return 1;
3383 }
3384
3385 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003386 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3387 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003388 SSL_CTX_free(ctx);
3389 return 1;
3390 }
3391
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003392 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003393 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003394 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3395 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003396 if (ret < 0) /* serious error, must do that ourselves */
3397 SSL_CTX_free(ctx);
3398 return 1;
3399 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003400
3401 if (SSL_CTX_check_private_key(ctx) <= 0) {
3402 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3403 err && *err ? *err : "", path);
3404 return 1;
3405 }
3406
Emeric Brunfc0421f2012-09-07 17:30:07 +02003407 /* we must not free the SSL_CTX anymore below, since it's already in
3408 * the tree, so it will be discovered and cleaned in time.
3409 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003410#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003411 /* store a NULL pointer to indicate we have not yet loaded
3412 a custom DH param file */
3413 if (ssl_dh_ptr_index >= 0) {
3414 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3415 }
3416
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003417 ret = ssl_sock_load_dh_params(ctx, path);
3418 if (ret < 0) {
3419 if (err)
3420 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3421 *err ? *err : "", path);
3422 return 1;
3423 }
3424#endif
3425
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003426#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003427 ret = ssl_sock_load_ocsp(ctx, path);
3428 if (ret < 0) {
3429 if (err)
3430 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",
3431 *err ? *err : "", path);
3432 return 1;
3433 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003434#elif (defined OPENSSL_IS_BORINGSSL)
3435 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003436#endif
3437
Daniel Jakots54ffb912015-11-06 20:02:41 +01003438#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003439 if (sctl_ex_index >= 0) {
3440 ret = ssl_sock_load_sctl(ctx, path);
3441 if (ret < 0) {
3442 if (err)
3443 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3444 *err ? *err : "", path);
3445 return 1;
3446 }
3447 }
3448#endif
3449
Emeric Brunfc0421f2012-09-07 17:30:07 +02003450#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003451 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003452 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3453 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003454 return 1;
3455 }
3456#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003457 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003458 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003459 bind_conf->default_ssl_conf = ssl_conf;
3460 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003461
3462 return 0;
3463}
3464
Willy Tarreau03209342016-12-22 17:08:28 +01003465int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003467 struct dirent **de_list;
3468 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003469 DIR *dir;
3470 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003471 char *end;
3472 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003473 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003474#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3475 int is_bundle;
3476 int j;
3477#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003478
yanbzhu08ce6ab2015-12-02 13:01:29 -05003479 if (stat(path, &buf) == 0) {
3480 dir = opendir(path);
3481 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003482 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003483
yanbzhu08ce6ab2015-12-02 13:01:29 -05003484 /* strip trailing slashes, including first one */
3485 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3486 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003487
yanbzhu08ce6ab2015-12-02 13:01:29 -05003488 n = scandir(path, &de_list, 0, alphasort);
3489 if (n < 0) {
3490 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3491 err && *err ? *err : "", path, strerror(errno));
3492 cfgerr++;
3493 }
3494 else {
3495 for (i = 0; i < n; i++) {
3496 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003497
yanbzhu08ce6ab2015-12-02 13:01:29 -05003498 end = strrchr(de->d_name, '.');
3499 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3500 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003501
yanbzhu08ce6ab2015-12-02 13:01:29 -05003502 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3503 if (stat(fp, &buf) != 0) {
3504 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3505 err && *err ? *err : "", fp, strerror(errno));
3506 cfgerr++;
3507 goto ignore_entry;
3508 }
3509 if (!S_ISREG(buf.st_mode))
3510 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003511
3512#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3513 is_bundle = 0;
3514 /* Check if current entry in directory is part of a multi-cert bundle */
3515
3516 if (end) {
3517 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3518 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3519 is_bundle = 1;
3520 break;
3521 }
3522 }
3523
3524 if (is_bundle) {
3525 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3526 int dp_len;
3527
3528 dp_len = end - de->d_name;
3529 snprintf(dp, dp_len + 1, "%s", de->d_name);
3530
3531 /* increment i and free de until we get to a non-bundle cert
3532 * Note here that we look at de_list[i + 1] before freeing de
3533 * this is important since ignore_entry will free de
3534 */
3535 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3536 free(de);
3537 i++;
3538 de = de_list[i];
3539 }
3540
3541 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003542 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003543
3544 /* Successfully processed the bundle */
3545 goto ignore_entry;
3546 }
3547 }
3548
3549#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003550 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003551ignore_entry:
3552 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003553 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003554 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003555 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003556 closedir(dir);
3557 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003558 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003559
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003560 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003561
Emeric Brunfc0421f2012-09-07 17:30:07 +02003562 return cfgerr;
3563}
3564
Thierry Fournier383085f2013-01-24 14:15:43 +01003565/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3566 * done once. Zero is returned if the operation fails. No error is returned
3567 * if the random is said as not implemented, because we expect that openssl
3568 * will use another method once needed.
3569 */
3570static int ssl_initialize_random()
3571{
3572 unsigned char random;
3573 static int random_initialized = 0;
3574
3575 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3576 random_initialized = 1;
3577
3578 return random_initialized;
3579}
3580
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003581/* release ssl bind conf */
3582void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003583{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003584 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003585#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003586 free(conf->npn_str);
3587 conf->npn_str = NULL;
3588#endif
3589#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3590 free(conf->alpn_str);
3591 conf->alpn_str = NULL;
3592#endif
3593 free(conf->ca_file);
3594 conf->ca_file = NULL;
3595 free(conf->crl_file);
3596 conf->crl_file = NULL;
3597 free(conf->ciphers);
3598 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003599#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3600 free(conf->ciphersuites);
3601 conf->ciphersuites = NULL;
3602#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003603 free(conf->curves);
3604 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003605 free(conf->ecdhe);
3606 conf->ecdhe = NULL;
3607 }
3608}
3609
3610int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3611{
3612 char thisline[CRT_LINESIZE];
3613 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003615 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003616 int linenum = 0;
3617 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003618
Willy Tarreauad1731d2013-04-02 17:35:58 +02003619 if ((f = fopen(file, "r")) == NULL) {
3620 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003621 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003622 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003623
3624 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003625 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003626 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003627 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003628 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003629 char *crt_path;
3630 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003631
3632 linenum++;
3633 end = line + strlen(line);
3634 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3635 /* Check if we reached the limit and the last char is not \n.
3636 * Watch out for the last line without the terminating '\n'!
3637 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003638 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3639 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003640 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003641 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003642 }
3643
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003644 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003645 newarg = 1;
3646 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003647 if (*line == '#' || *line == '\n' || *line == '\r') {
3648 /* end of string, end of loop */
3649 *line = 0;
3650 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003651 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003652 newarg = 1;
3653 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003654 } else if (*line == '[') {
3655 if (ssl_b) {
3656 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3657 cfgerr = 1;
3658 break;
3659 }
3660 if (!arg) {
3661 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3662 cfgerr = 1;
3663 break;
3664 }
3665 ssl_b = arg;
3666 newarg = 1;
3667 *line = 0;
3668 } else if (*line == ']') {
3669 if (ssl_e) {
3670 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003671 cfgerr = 1;
3672 break;
3673 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003674 if (!ssl_b) {
3675 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3676 cfgerr = 1;
3677 break;
3678 }
3679 ssl_e = arg;
3680 newarg = 1;
3681 *line = 0;
3682 } else if (newarg) {
3683 if (arg == MAX_CRT_ARGS) {
3684 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3685 cfgerr = 1;
3686 break;
3687 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003688 newarg = 0;
3689 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003690 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003691 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003692 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003693 if (cfgerr)
3694 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003695 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003696
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003697 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003698 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003699 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003700
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003701 crt_path = args[0];
3702 if (*crt_path != '/' && global_ssl.crt_base) {
3703 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3704 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3705 crt_path, linenum, file);
3706 cfgerr = 1;
3707 break;
3708 }
3709 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3710 crt_path = path;
3711 }
3712
3713 ssl_conf = calloc(1, sizeof *ssl_conf);
3714 cur_arg = ssl_b ? ssl_b : 1;
3715 while (cur_arg < ssl_e) {
3716 newarg = 0;
3717 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3718 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3719 newarg = 1;
3720 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3721 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3722 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3723 args[cur_arg], linenum, file);
3724 cfgerr = 1;
3725 }
3726 cur_arg += 1 + ssl_bind_kws[i].skip;
3727 break;
3728 }
3729 }
3730 if (!cfgerr && !newarg) {
3731 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3732 args[cur_arg], linenum, file);
3733 cfgerr = 1;
3734 break;
3735 }
3736 }
3737 if (cfgerr) {
3738 ssl_sock_free_ssl_conf(ssl_conf);
3739 free(ssl_conf);
3740 ssl_conf = NULL;
3741 break;
3742 }
3743
3744 if (stat(crt_path, &buf) == 0) {
3745 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3746 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003747 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003748 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3749 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003750 }
3751
Willy Tarreauad1731d2013-04-02 17:35:58 +02003752 if (cfgerr) {
3753 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003754 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003755 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003756 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003757 fclose(f);
3758 return cfgerr;
3759}
3760
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003761/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003762static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003763ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003764{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003765 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003766 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003767 SSL_OP_ALL | /* all known workarounds for bugs */
3768 SSL_OP_NO_SSLv2 |
3769 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003770 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003771 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003772 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003773 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003774 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003776 SSL_MODE_ENABLE_PARTIAL_WRITE |
3777 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003778 SSL_MODE_RELEASE_BUFFERS |
3779 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003780 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003781 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003782 int flags = MC_SSL_O_ALL;
3783 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003784
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003785 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003786 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003787
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003788 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003789 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3790 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3791 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003792 else
3793 flags = conf_ssl_methods->flags;
3794
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003795 min = conf_ssl_methods->min;
3796 max = conf_ssl_methods->max;
3797 /* start with TLSv10 to remove SSLv3 per default */
3798 if (!min && (!max || max >= CONF_TLSV10))
3799 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003800 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003801 if (min)
3802 flags |= (methodVersions[min].flag - 1);
3803 if (max)
3804 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003805 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003806 min = max = CONF_TLSV_NONE;
3807 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003808 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003809 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003810 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003811 if (min) {
3812 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003813 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3814 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3815 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3816 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003817 hole = 0;
3818 }
3819 max = i;
3820 }
3821 else {
3822 min = max = i;
3823 }
3824 }
3825 else {
3826 if (min)
3827 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003828 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003829 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003830 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3831 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003832 cfgerr += 1;
3833 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003834 /* save real min/max in bind_conf */
3835 conf_ssl_methods->min = min;
3836 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003837
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003838#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003839 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003840 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003841 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003842 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003843 else
3844 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3845 if (flags & methodVersions[i].flag)
3846 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003847#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003848 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003849 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3850 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003851#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003852
3853 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3854 options |= SSL_OP_NO_TICKET;
3855 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3856 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3857 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003858
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003859#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003860 if (global_ssl.async)
3861 mode |= SSL_MODE_ASYNC;
3862#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003863 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003864 if (global_ssl.life_time)
3865 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003866
3867#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3868#ifdef OPENSSL_IS_BORINGSSL
3869 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3870 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003871#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3872 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3873 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003874#else
3875 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003876#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003877 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003878#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003879 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003880}
3881
William Lallemand4f45bb92017-10-30 20:08:51 +01003882
3883static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3884{
3885 if (first == block) {
3886 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3887 if (first->len > 0)
3888 sh_ssl_sess_tree_delete(sh_ssl_sess);
3889 }
3890}
3891
3892/* return first block from sh_ssl_sess */
3893static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3894{
3895 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3896
3897}
3898
3899/* store a session into the cache
3900 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3901 * data: asn1 encoded session
3902 * data_len: asn1 encoded session length
3903 * Returns 1 id session was stored (else 0)
3904 */
3905static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3906{
3907 struct shared_block *first;
3908 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3909
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003910 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003911 if (!first) {
3912 /* Could not retrieve enough free blocks to store that session */
3913 return 0;
3914 }
3915
3916 /* STORE the key in the first elem */
3917 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3918 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3919 first->len = sizeof(struct sh_ssl_sess_hdr);
3920
3921 /* it returns the already existing node
3922 or current node if none, never returns null */
3923 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3924 if (oldsh_ssl_sess != sh_ssl_sess) {
3925 /* NOTE: Row couldn't be in use because we lock read & write function */
3926 /* release the reserved row */
3927 shctx_row_dec_hot(ssl_shctx, first);
3928 /* replace the previous session already in the tree */
3929 sh_ssl_sess = oldsh_ssl_sess;
3930 /* ignore the previous session data, only use the header */
3931 first = sh_ssl_sess_first_block(sh_ssl_sess);
3932 shctx_row_inc_hot(ssl_shctx, first);
3933 first->len = sizeof(struct sh_ssl_sess_hdr);
3934 }
3935
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003936 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003937 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003938 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003939 }
3940
3941 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003942
3943 return 1;
3944}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003945
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003946/* SSL callback used when a new session is created while connecting to a server */
3947static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3948{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003949 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003950 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003951
Willy Tarreau07d94e42018-09-20 10:57:52 +02003952 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003953
Olivier Houcharde6060c52017-11-16 17:42:52 +01003954 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3955 int len;
3956 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003957
Olivier Houcharde6060c52017-11-16 17:42:52 +01003958 len = i2d_SSL_SESSION(sess, NULL);
3959 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3960 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3961 } else {
3962 free(s->ssl_ctx.reused_sess[tid].ptr);
3963 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3964 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3965 }
3966 if (s->ssl_ctx.reused_sess[tid].ptr) {
3967 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3968 &ptr);
3969 }
3970 } else {
3971 free(s->ssl_ctx.reused_sess[tid].ptr);
3972 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3973 }
3974
3975 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003976}
3977
Olivier Houcharde6060c52017-11-16 17:42:52 +01003978
William Lallemanded0b5ad2017-10-30 19:36:36 +01003979/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003980int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003981{
3982 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3983 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3984 unsigned char *p;
3985 int data_len;
3986 unsigned int sid_length, sid_ctx_length;
3987 const unsigned char *sid_data;
3988 const unsigned char *sid_ctx_data;
3989
3990 /* Session id is already stored in to key and session id is known
3991 * so we dont store it to keep size.
3992 */
3993
3994 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3995 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3996 SSL_SESSION_set1_id(sess, sid_data, 0);
3997 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3998
3999 /* check if buffer is large enough for the ASN1 encoded session */
4000 data_len = i2d_SSL_SESSION(sess, NULL);
4001 if (data_len > SHSESS_MAX_DATA_LEN)
4002 goto err;
4003
4004 p = encsess;
4005
4006 /* process ASN1 session encoding before the lock */
4007 i2d_SSL_SESSION(sess, &p);
4008
4009 memcpy(encid, sid_data, sid_length);
4010 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4011 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4012
William Lallemanda3c77cf2017-10-30 23:44:40 +01004013 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004014 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004015 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004016 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004017err:
4018 /* reset original length values */
4019 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4020 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4021
4022 return 0; /* do not increment session reference count */
4023}
4024
4025/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004026SSL_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 +01004027{
William Lallemand4f45bb92017-10-30 20:08:51 +01004028 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004029 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4030 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004031 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004032 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004033
4034 global.shctx_lookups++;
4035
4036 /* allow the session to be freed automatically by openssl */
4037 *do_copy = 0;
4038
4039 /* tree key is zeros padded sessionid */
4040 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4041 memcpy(tmpkey, key, key_len);
4042 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4043 key = tmpkey;
4044 }
4045
4046 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004047 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004048
4049 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004050 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4051 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004052 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004053 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004054 global.shctx_misses++;
4055 return NULL;
4056 }
4057
William Lallemand4f45bb92017-10-30 20:08:51 +01004058 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4059 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004060
William Lallemand4f45bb92017-10-30 20:08:51 +01004061 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 +01004062
William Lallemanda3c77cf2017-10-30 23:44:40 +01004063 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004064
4065 /* decode ASN1 session */
4066 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004067 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004068 /* Reset session id and session id contenxt */
4069 if (sess) {
4070 SSL_SESSION_set1_id(sess, key, key_len);
4071 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4072 }
4073
4074 return sess;
4075}
4076
William Lallemand4f45bb92017-10-30 20:08:51 +01004077
William Lallemanded0b5ad2017-10-30 19:36:36 +01004078/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004079void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004080{
William Lallemand4f45bb92017-10-30 20:08:51 +01004081 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004082 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4083 unsigned int sid_length;
4084 const unsigned char *sid_data;
4085 (void)ctx;
4086
4087 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4088 /* tree key is zeros padded sessionid */
4089 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4090 memcpy(tmpkey, sid_data, sid_length);
4091 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4092 sid_data = tmpkey;
4093 }
4094
William Lallemanda3c77cf2017-10-30 23:44:40 +01004095 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004096
4097 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004098 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4099 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004100 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004101 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004102 }
4103
4104 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004105 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004106}
4107
4108/* Set session cache mode to server and disable openssl internal cache.
4109 * Set shared cache callbacks on an ssl context.
4110 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004111void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004112{
4113 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4114
4115 if (!ssl_shctx) {
4116 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4117 return;
4118 }
4119
4120 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4121 SSL_SESS_CACHE_NO_INTERNAL |
4122 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4123
4124 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004125 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4126 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4127 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004128}
4129
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004130int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4131{
4132 struct proxy *curproxy = bind_conf->frontend;
4133 int cfgerr = 0;
4134 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004135 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004136 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004137#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4138 const char *conf_ciphersuites;
4139#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004140 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004141
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004142 if (ssl_conf) {
4143 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4144 int i, min, max;
4145 int flags = MC_SSL_O_ALL;
4146
4147 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004148 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4149 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004150 if (min)
4151 flags |= (methodVersions[min].flag - 1);
4152 if (max)
4153 flags |= ~((methodVersions[max].flag << 1) - 1);
4154 min = max = CONF_TLSV_NONE;
4155 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4156 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4157 if (min)
4158 max = i;
4159 else
4160 min = max = i;
4161 }
4162 /* save real min/max */
4163 conf_ssl_methods->min = min;
4164 conf_ssl_methods->max = max;
4165 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004166 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4167 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004168 cfgerr += 1;
4169 }
4170 }
4171
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004172 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004173 case SSL_SOCK_VERIFY_NONE:
4174 verify = SSL_VERIFY_NONE;
4175 break;
4176 case SSL_SOCK_VERIFY_OPTIONAL:
4177 verify = SSL_VERIFY_PEER;
4178 break;
4179 case SSL_SOCK_VERIFY_REQUIRED:
4180 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4181 break;
4182 }
4183 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4184 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004185 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4186 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4187 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004188 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004189 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004190 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4191 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004192 cfgerr++;
4193 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004194 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4195 /* set CA names for client cert request, function returns void */
4196 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4197 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004198 }
Emeric Brun850efd52014-01-29 12:24:34 +01004199 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004200 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4201 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004202 cfgerr++;
4203 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004204#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004205 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004206 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4207
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004208 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004209 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4210 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004211 cfgerr++;
4212 }
Emeric Brun561e5742012-10-02 15:20:55 +02004213 else {
4214 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4215 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004216 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004217#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004218 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004219 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004220#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004221 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004222 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004223 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4224 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004225 cfgerr++;
4226 }
4227 }
4228#endif
4229
William Lallemand4f45bb92017-10-30 20:08:51 +01004230 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004231 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4232 if (conf_ciphers &&
4233 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004234 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4235 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004236 cfgerr++;
4237 }
4238
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004239#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4240 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4241 if (conf_ciphersuites &&
4242 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4243 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4244 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4245 cfgerr++;
4246 }
4247#endif
4248
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004249#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004250 /* If tune.ssl.default-dh-param has not been set,
4251 neither has ssl-default-dh-file and no static DH
4252 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004253 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004254 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004255 (ssl_dh_ptr_index == -1 ||
4256 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004257 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4258 const SSL_CIPHER * cipher = NULL;
4259 char cipher_description[128];
4260 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4261 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4262 which is not ephemeral DH. */
4263 const char dhe_description[] = " Kx=DH ";
4264 const char dhe_export_description[] = " Kx=DH(";
4265 int idx = 0;
4266 int dhe_found = 0;
4267 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004268
Remi Gacogne23d5d372014-10-10 17:04:26 +02004269 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004270
Remi Gacogne23d5d372014-10-10 17:04:26 +02004271 if (ssl) {
4272 ciphers = SSL_get_ciphers(ssl);
4273
4274 if (ciphers) {
4275 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4276 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4277 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4278 if (strstr(cipher_description, dhe_description) != NULL ||
4279 strstr(cipher_description, dhe_export_description) != NULL) {
4280 dhe_found = 1;
4281 break;
4282 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004283 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004284 }
4285 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004286 SSL_free(ssl);
4287 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004288 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004289
Lukas Tribus90132722014-08-18 00:56:33 +02004290 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004291 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 +02004292 }
4293
Willy Tarreauef934602016-12-22 23:12:01 +01004294 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004295 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004296
Willy Tarreauef934602016-12-22 23:12:01 +01004297 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004298 if (local_dh_1024 == NULL) {
4299 local_dh_1024 = ssl_get_dh_1024();
4300 }
Willy Tarreauef934602016-12-22 23:12:01 +01004301 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004302 if (local_dh_2048 == NULL) {
4303 local_dh_2048 = ssl_get_dh_2048();
4304 }
Willy Tarreauef934602016-12-22 23:12:01 +01004305 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004306 if (local_dh_4096 == NULL) {
4307 local_dh_4096 = ssl_get_dh_4096();
4308 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004309 }
4310 }
4311 }
4312#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004313
Emeric Brunfc0421f2012-09-07 17:30:07 +02004314 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004315#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004316 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004317#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004318
Bernard Spil13c53f82018-02-15 13:34:58 +01004319#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004320 ssl_conf_cur = NULL;
4321 if (ssl_conf && ssl_conf->npn_str)
4322 ssl_conf_cur = ssl_conf;
4323 else if (bind_conf->ssl_conf.npn_str)
4324 ssl_conf_cur = &bind_conf->ssl_conf;
4325 if (ssl_conf_cur)
4326 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004327#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004328#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004329 ssl_conf_cur = NULL;
4330 if (ssl_conf && ssl_conf->alpn_str)
4331 ssl_conf_cur = ssl_conf;
4332 else if (bind_conf->ssl_conf.alpn_str)
4333 ssl_conf_cur = &bind_conf->ssl_conf;
4334 if (ssl_conf_cur)
4335 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004336#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004337#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4338 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4339 if (conf_curves) {
4340 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004341 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4342 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004343 cfgerr++;
4344 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004345#if defined(SSL_CTX_set_ecdh_auto)
4346 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4347#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004348 }
4349#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004350#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004351 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004352 int i;
4353 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004354#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004355 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004356 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4357 NULL);
4358
4359 if (ecdhe == NULL) {
4360 SSL_CTX_set_dh_auto(ctx, 1);
4361 return cfgerr;
4362 }
4363#else
4364 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4365 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4366 ECDHE_DEFAULT_CURVE);
4367#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004368
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004369 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004370 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004371 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4372 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004373 cfgerr++;
4374 }
4375 else {
4376 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4377 EC_KEY_free(ecdh);
4378 }
4379 }
4380#endif
4381
Emeric Brunfc0421f2012-09-07 17:30:07 +02004382 return cfgerr;
4383}
4384
Evan Broderbe554312013-06-27 00:05:25 -07004385static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4386{
4387 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4388 size_t prefixlen, suffixlen;
4389
4390 /* Trivial case */
4391 if (strcmp(pattern, hostname) == 0)
4392 return 1;
4393
Evan Broderbe554312013-06-27 00:05:25 -07004394 /* The rest of this logic is based on RFC 6125, section 6.4.3
4395 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4396
Emeric Bruna848dae2013-10-08 11:27:28 +02004397 pattern_wildcard = NULL;
4398 pattern_left_label_end = pattern;
4399 while (*pattern_left_label_end != '.') {
4400 switch (*pattern_left_label_end) {
4401 case 0:
4402 /* End of label not found */
4403 return 0;
4404 case '*':
4405 /* If there is more than one wildcards */
4406 if (pattern_wildcard)
4407 return 0;
4408 pattern_wildcard = pattern_left_label_end;
4409 break;
4410 }
4411 pattern_left_label_end++;
4412 }
4413
4414 /* If it's not trivial and there is no wildcard, it can't
4415 * match */
4416 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004417 return 0;
4418
4419 /* Make sure all labels match except the leftmost */
4420 hostname_left_label_end = strchr(hostname, '.');
4421 if (!hostname_left_label_end
4422 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4423 return 0;
4424
4425 /* Make sure the leftmost label of the hostname is long enough
4426 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004427 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004428 return 0;
4429
4430 /* Finally compare the string on either side of the
4431 * wildcard */
4432 prefixlen = pattern_wildcard - pattern;
4433 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004434 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4435 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004436 return 0;
4437
4438 return 1;
4439}
4440
4441static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4442{
4443 SSL *ssl;
4444 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004445 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004446 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004447
4448 int depth;
4449 X509 *cert;
4450 STACK_OF(GENERAL_NAME) *alt_names;
4451 int i;
4452 X509_NAME *cert_subject;
4453 char *str;
4454
4455 if (ok == 0)
4456 return ok;
4457
4458 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004459 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004460
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004461 /* We're checking if the provided hostnames match the desired one. The
4462 * desired hostname comes from the SNI we presented if any, or if not
4463 * provided then it may have been explicitly stated using a "verifyhost"
4464 * directive. If neither is set, we don't care about the name so the
4465 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004466 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004467 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004468 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004469 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004470 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004471 if (!servername)
4472 return ok;
4473 }
Evan Broderbe554312013-06-27 00:05:25 -07004474
4475 /* We only need to verify the CN on the actual server cert,
4476 * not the indirect CAs */
4477 depth = X509_STORE_CTX_get_error_depth(ctx);
4478 if (depth != 0)
4479 return ok;
4480
4481 /* At this point, the cert is *not* OK unless we can find a
4482 * hostname match */
4483 ok = 0;
4484
4485 cert = X509_STORE_CTX_get_current_cert(ctx);
4486 /* It seems like this might happen if verify peer isn't set */
4487 if (!cert)
4488 return ok;
4489
4490 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4491 if (alt_names) {
4492 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4493 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4494 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004495#if OPENSSL_VERSION_NUMBER < 0x00907000L
4496 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4497#else
Evan Broderbe554312013-06-27 00:05:25 -07004498 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004499#endif
Evan Broderbe554312013-06-27 00:05:25 -07004500 ok = ssl_sock_srv_hostcheck(str, servername);
4501 OPENSSL_free(str);
4502 }
4503 }
4504 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004505 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004506 }
4507
4508 cert_subject = X509_get_subject_name(cert);
4509 i = -1;
4510 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4511 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004512 ASN1_STRING *value;
4513 value = X509_NAME_ENTRY_get_data(entry);
4514 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004515 ok = ssl_sock_srv_hostcheck(str, servername);
4516 OPENSSL_free(str);
4517 }
4518 }
4519
Willy Tarreau71d058c2017-07-26 20:09:56 +02004520 /* report the mismatch and indicate if SNI was used or not */
4521 if (!ok && !conn->err_code)
4522 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004523 return ok;
4524}
4525
Emeric Brun94324a42012-10-11 14:00:19 +02004526/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004527int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004528{
Willy Tarreau03209342016-12-22 17:08:28 +01004529 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004530 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004531 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004532 SSL_OP_ALL | /* all known workarounds for bugs */
4533 SSL_OP_NO_SSLv2 |
4534 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004535 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004536 SSL_MODE_ENABLE_PARTIAL_WRITE |
4537 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004538 SSL_MODE_RELEASE_BUFFERS |
4539 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004540 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004541 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004542 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004543 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004544 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004545
Thierry Fournier383085f2013-01-24 14:15:43 +01004546 /* Make sure openssl opens /dev/urandom before the chroot */
4547 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004548 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004549 cfgerr++;
4550 }
4551
Willy Tarreaufce03112015-01-15 21:32:40 +01004552 /* Automatic memory computations need to know we use SSL there */
4553 global.ssl_used_backend = 1;
4554
4555 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004556 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004557 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004558 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4559 curproxy->id, srv->id,
4560 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004561 cfgerr++;
4562 return cfgerr;
4563 }
4564 }
Emeric Brun94324a42012-10-11 14:00:19 +02004565 if (srv->use_ssl)
4566 srv->xprt = &ssl_sock;
4567 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004568 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004569
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004570 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004571 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004572 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4573 proxy_type_str(curproxy), curproxy->id,
4574 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004575 cfgerr++;
4576 return cfgerr;
4577 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004578
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004579 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004580 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4581 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4582 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004583 else
4584 flags = conf_ssl_methods->flags;
4585
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004586 /* Real min and max should be determinate with configuration and openssl's capabilities */
4587 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004588 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004589 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004590 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004591
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004592 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004593 min = max = CONF_TLSV_NONE;
4594 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004595 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004596 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004597 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004598 if (min) {
4599 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004600 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4601 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4602 proxy_type_str(curproxy), curproxy->id, srv->id,
4603 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004604 hole = 0;
4605 }
4606 max = i;
4607 }
4608 else {
4609 min = max = i;
4610 }
4611 }
4612 else {
4613 if (min)
4614 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004615 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004616 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004617 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4618 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004619 cfgerr += 1;
4620 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004621
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004622#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004623 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004624 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004625 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004626 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004627 else
4628 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4629 if (flags & methodVersions[i].flag)
4630 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004631#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004632 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004633 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4634 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004635#endif
4636
4637 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4638 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004639 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004640
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004641#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004642 if (global_ssl.async)
4643 mode |= SSL_MODE_ASYNC;
4644#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004645 SSL_CTX_set_mode(ctx, mode);
4646 srv->ssl_ctx.ctx = ctx;
4647
Emeric Bruna7aa3092012-10-26 12:58:00 +02004648 if (srv->ssl_ctx.client_crt) {
4649 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 +01004650 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4651 proxy_type_str(curproxy), curproxy->id,
4652 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004653 cfgerr++;
4654 }
4655 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 +01004656 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4657 proxy_type_str(curproxy), curproxy->id,
4658 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004659 cfgerr++;
4660 }
4661 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004662 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4663 proxy_type_str(curproxy), curproxy->id,
4664 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004665 cfgerr++;
4666 }
4667 }
Emeric Brun94324a42012-10-11 14:00:19 +02004668
Emeric Brun850efd52014-01-29 12:24:34 +01004669 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4670 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004671 switch (srv->ssl_ctx.verify) {
4672 case SSL_SOCK_VERIFY_NONE:
4673 verify = SSL_VERIFY_NONE;
4674 break;
4675 case SSL_SOCK_VERIFY_REQUIRED:
4676 verify = SSL_VERIFY_PEER;
4677 break;
4678 }
Evan Broderbe554312013-06-27 00:05:25 -07004679 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004680 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004681 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004682 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004683 if (srv->ssl_ctx.ca_file) {
4684 /* load CAfile to verify */
4685 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004686 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4687 curproxy->id, srv->id,
4688 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004689 cfgerr++;
4690 }
4691 }
Emeric Brun850efd52014-01-29 12:24:34 +01004692 else {
4693 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004694 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",
4695 curproxy->id, srv->id,
4696 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004697 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004698 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4699 curproxy->id, srv->id,
4700 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004701 cfgerr++;
4702 }
Emeric Brunef42d922012-10-11 16:11:36 +02004703#ifdef X509_V_FLAG_CRL_CHECK
4704 if (srv->ssl_ctx.crl_file) {
4705 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4706
4707 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004708 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4709 curproxy->id, srv->id,
4710 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004711 cfgerr++;
4712 }
4713 else {
4714 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4715 }
4716 }
4717#endif
4718 }
4719
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004720 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4721 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4722 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004723 if (srv->ssl_ctx.ciphers &&
4724 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004725 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4726 curproxy->id, srv->id,
4727 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004728 cfgerr++;
4729 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004730
4731#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4732 if (srv->ssl_ctx.ciphersuites &&
4733 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4734 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4735 curproxy->id, srv->id,
4736 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4737 cfgerr++;
4738 }
4739#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004740#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4741 if (srv->ssl_ctx.npn_str)
4742 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4743#endif
4744#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4745 if (srv->ssl_ctx.alpn_str)
4746 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4747#endif
4748
Emeric Brun94324a42012-10-11 14:00:19 +02004749
4750 return cfgerr;
4751}
4752
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004753/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004754 * be NULL, in which case nothing is done. Returns the number of errors
4755 * encountered.
4756 */
Willy Tarreau03209342016-12-22 17:08:28 +01004757int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004758{
4759 struct ebmb_node *node;
4760 struct sni_ctx *sni;
4761 int err = 0;
4762
Willy Tarreaufce03112015-01-15 21:32:40 +01004763 /* Automatic memory computations need to know we use SSL there */
4764 global.ssl_used_frontend = 1;
4765
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004766 /* Make sure openssl opens /dev/urandom before the chroot */
4767 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004768 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004769 err++;
4770 }
4771 /* Create initial_ctx used to start the ssl connection before do switchctx */
4772 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004773 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004774 /* It should not be necessary to call this function, but it's
4775 necessary first to check and move all initialisation related
4776 to initial_ctx in ssl_sock_initial_ctx. */
4777 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4778 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004779 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004780 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004781
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004782 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004783 while (node) {
4784 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004785 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4786 /* only initialize the CTX on its first occurrence and
4787 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004788 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004789 node = ebmb_next(node);
4790 }
4791
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004792 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004793 while (node) {
4794 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004795 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4796 /* only initialize the CTX on its first occurrence and
4797 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004798 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004799 node = ebmb_next(node);
4800 }
4801 return err;
4802}
4803
Willy Tarreau55d37912016-12-21 23:38:39 +01004804/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4805 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4806 * alerts are directly emitted since the rest of the stack does it below.
4807 */
4808int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4809{
4810 struct proxy *px = bind_conf->frontend;
4811 int alloc_ctx;
4812 int err;
4813
4814 if (!bind_conf->is_ssl) {
4815 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004816 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4817 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004818 }
4819 return 0;
4820 }
4821 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004822 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004823 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4824 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004825 }
4826 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004827 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4828 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004829 return -1;
4830 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004831 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004832 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004833 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004834 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004835 sizeof(*sh_ssl_sess_tree),
4836 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004837 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004838 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4839 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");
4840 else
4841 ha_alert("Unable to allocate SSL session cache.\n");
4842 return -1;
4843 }
4844 /* free block callback */
4845 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4846 /* init the root tree within the extra space */
4847 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4848 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004849 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004850 err = 0;
4851 /* initialize all certificate contexts */
4852 err += ssl_sock_prepare_all_ctx(bind_conf);
4853
4854 /* initialize CA variables if the certificates generation is enabled */
4855 err += ssl_sock_load_ca(bind_conf);
4856
4857 return -err;
4858}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004859
4860/* release ssl context allocated for servers. */
4861void ssl_sock_free_srv_ctx(struct server *srv)
4862{
Olivier Houchardc7566002018-11-20 23:33:50 +01004863#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4864 if (srv->ssl_ctx.alpn_str)
4865 free(srv->ssl_ctx.alpn_str);
4866#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004867#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004868 if (srv->ssl_ctx.npn_str)
4869 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01004870#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004871 if (srv->ssl_ctx.ctx)
4872 SSL_CTX_free(srv->ssl_ctx.ctx);
4873}
4874
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004875/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004876 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4877 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004878void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004879{
4880 struct ebmb_node *node, *back;
4881 struct sni_ctx *sni;
4882
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004883 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004884 while (node) {
4885 sni = ebmb_entry(node, struct sni_ctx, name);
4886 back = ebmb_next(node);
4887 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004888 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004889 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004890 ssl_sock_free_ssl_conf(sni->conf);
4891 free(sni->conf);
4892 sni->conf = NULL;
4893 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004894 free(sni);
4895 node = back;
4896 }
4897
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004898 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004899 while (node) {
4900 sni = ebmb_entry(node, struct sni_ctx, name);
4901 back = ebmb_next(node);
4902 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004903 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004904 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004905 ssl_sock_free_ssl_conf(sni->conf);
4906 free(sni->conf);
4907 sni->conf = NULL;
4908 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004909 free(sni);
4910 node = back;
4911 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004912 SSL_CTX_free(bind_conf->initial_ctx);
4913 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004914 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004915 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004916}
4917
Willy Tarreau795cdab2016-12-22 17:30:54 +01004918/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4919void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4920{
4921 ssl_sock_free_ca(bind_conf);
4922 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004923 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004924 free(bind_conf->ca_sign_file);
4925 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004926 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004927 free(bind_conf->keys_ref->filename);
4928 free(bind_conf->keys_ref->tlskeys);
4929 LIST_DEL(&bind_conf->keys_ref->list);
4930 free(bind_conf->keys_ref);
4931 }
4932 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004933 bind_conf->ca_sign_pass = NULL;
4934 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004935}
4936
Christopher Faulet31af49d2015-06-09 17:29:50 +02004937/* Load CA cert file and private key used to generate certificates */
4938int
Willy Tarreau03209342016-12-22 17:08:28 +01004939ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004940{
Willy Tarreau03209342016-12-22 17:08:28 +01004941 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004942 FILE *fp;
4943 X509 *cacert = NULL;
4944 EVP_PKEY *capkey = NULL;
4945 int err = 0;
4946
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004947 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004948 return err;
4949
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004950#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004951 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004952 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004953 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004954 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004955 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004956#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004957
Christopher Faulet31af49d2015-06-09 17:29:50 +02004958 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004959 ha_alert("Proxy '%s': cannot enable certificate generation, "
4960 "no CA certificate File configured at [%s:%d].\n",
4961 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004962 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004963 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004964
4965 /* read in the CA certificate */
4966 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004967 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4968 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004969 goto load_error;
4970 }
4971 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004972 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4973 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004974 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004975 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004976 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004977 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004978 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4979 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004980 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004981 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004982
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004983 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004984 bind_conf->ca_sign_cert = cacert;
4985 bind_conf->ca_sign_pkey = capkey;
4986 return err;
4987
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004988 read_error:
4989 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004990 if (capkey) EVP_PKEY_free(capkey);
4991 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004992 load_error:
4993 bind_conf->generate_certs = 0;
4994 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004995 return err;
4996}
4997
4998/* Release CA cert and private key used to generate certificated */
4999void
5000ssl_sock_free_ca(struct bind_conf *bind_conf)
5001{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005002 if (bind_conf->ca_sign_pkey)
5003 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5004 if (bind_conf->ca_sign_cert)
5005 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005006 bind_conf->ca_sign_pkey = NULL;
5007 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005008}
5009
Emeric Brun46591952012-05-18 15:47:34 +02005010/*
5011 * This function is called if SSL * context is not yet allocated. The function
5012 * is designed to be called before any other data-layer operation and sets the
5013 * handshake flag on the connection. It is safe to call it multiple times.
5014 * It returns 0 on success and -1 in error case.
5015 */
5016static int ssl_sock_init(struct connection *conn)
5017{
5018 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005019 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005020 return 0;
5021
Willy Tarreau3c728722014-01-23 13:50:42 +01005022 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005023 return 0;
5024
Willy Tarreau20879a02012-12-03 16:32:10 +01005025 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5026 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005027 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005028 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005029
Emeric Brun46591952012-05-18 15:47:34 +02005030 /* If it is in client mode initiate SSL session
5031 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005032 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005033 int may_retry = 1;
5034
5035 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005036 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005037 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005038 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005039 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005040 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005041 goto retry_connect;
5042 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005043 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005044 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005045 }
Emeric Brun46591952012-05-18 15:47:34 +02005046
Emeric Brun46591952012-05-18 15:47:34 +02005047 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005048 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005049 SSL_free(conn->xprt_ctx);
5050 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005051 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005052 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005053 goto retry_connect;
5054 }
Emeric Brun55476152014-11-12 17:35:37 +01005055 conn->err_code = CO_ER_SSL_NO_MEM;
5056 return -1;
5057 }
Emeric Brun46591952012-05-18 15:47:34 +02005058
Evan Broderbe554312013-06-27 00:05:25 -07005059 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005060 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005061 SSL_free(conn->xprt_ctx);
5062 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005063 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005064 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005065 goto retry_connect;
5066 }
Emeric Brun55476152014-11-12 17:35:37 +01005067 conn->err_code = CO_ER_SSL_NO_MEM;
5068 return -1;
5069 }
5070
5071 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005072 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5073 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5074 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5075 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005076 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005077 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5078 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005079 } else if (sess) {
5080 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005081 }
5082 }
Evan Broderbe554312013-06-27 00:05:25 -07005083
Emeric Brun46591952012-05-18 15:47:34 +02005084 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005085 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005086
Emeric Brun7ad43e72018-10-10 14:51:02 +02005087 HA_ATOMIC_ADD(&sslconns, 1);
5088 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005089 return 0;
5090 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005091 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005092 int may_retry = 1;
5093
5094 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005095 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005096 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005097 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005098 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005099 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005100 goto retry_accept;
5101 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005102 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005103 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005104 }
Emeric Brun46591952012-05-18 15:47:34 +02005105
Emeric Brun46591952012-05-18 15:47:34 +02005106 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005107 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005108 SSL_free(conn->xprt_ctx);
5109 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005110 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005111 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005112 goto retry_accept;
5113 }
Emeric Brun55476152014-11-12 17:35:37 +01005114 conn->err_code = CO_ER_SSL_NO_MEM;
5115 return -1;
5116 }
Emeric Brun46591952012-05-18 15:47:34 +02005117
Emeric Brune1f38db2012-09-03 20:36:47 +02005118 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005119 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005120 SSL_free(conn->xprt_ctx);
5121 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005122 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005123 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005124 goto retry_accept;
5125 }
Emeric Brun55476152014-11-12 17:35:37 +01005126 conn->err_code = CO_ER_SSL_NO_MEM;
5127 return -1;
5128 }
5129
5130 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005131
Emeric Brun46591952012-05-18 15:47:34 +02005132 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005133 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005134#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005135 conn->flags |= CO_FL_EARLY_SSL_HS;
5136#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005137
Emeric Brun7ad43e72018-10-10 14:51:02 +02005138 HA_ATOMIC_ADD(&sslconns, 1);
5139 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005140 return 0;
5141 }
5142 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005143 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005144 return -1;
5145}
5146
5147
5148/* This is the callback which is used when an SSL handshake is pending. It
5149 * updates the FD status if it wants some polling before being called again.
5150 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5151 * otherwise it returns non-zero and removes itself from the connection's
5152 * flags (the bit is provided in <flag> by the caller).
5153 */
5154int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5155{
5156 int ret;
5157
Willy Tarreau3c728722014-01-23 13:50:42 +01005158 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005159 return 0;
5160
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005161 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005162 goto out_error;
5163
Olivier Houchardc2aae742017-09-22 18:26:28 +02005164#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5165 /*
5166 * Check if we have early data. If we do, we have to read them
5167 * before SSL_do_handshake() is called, And there's no way to
5168 * detect early data, except to try to read them
5169 */
5170 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5171 size_t read_data;
5172
5173 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5174 1, &read_data);
5175 if (ret == SSL_READ_EARLY_DATA_ERROR)
5176 goto check_error;
5177 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5178 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5179 return 1;
5180 } else
5181 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5182 }
5183#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005184 /* If we use SSL_do_handshake to process a reneg initiated by
5185 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5186 * Usually SSL_write and SSL_read are used and process implicitly
5187 * the reneg handshake.
5188 * Here we use SSL_peek as a workaround for reneg.
5189 */
5190 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5191 char c;
5192
5193 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5194 if (ret <= 0) {
5195 /* handshake may have not been completed, let's find why */
5196 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005197
Emeric Brun674b7432012-11-08 19:21:55 +01005198 if (ret == SSL_ERROR_WANT_WRITE) {
5199 /* SSL handshake needs to write, L4 connection may not be ready */
5200 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005201 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005202 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005203 return 0;
5204 }
5205 else if (ret == SSL_ERROR_WANT_READ) {
5206 /* handshake may have been completed but we have
5207 * no more data to read.
5208 */
5209 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5210 ret = 1;
5211 goto reneg_ok;
5212 }
5213 /* SSL handshake needs to read, L4 connection is ready */
5214 if (conn->flags & CO_FL_WAIT_L4_CONN)
5215 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5216 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005217 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005218 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005219 return 0;
5220 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005221#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005222 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005223 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005224 return 0;
5225 }
5226#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005227 else if (ret == SSL_ERROR_SYSCALL) {
5228 /* if errno is null, then connection was successfully established */
5229 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5230 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005231 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005232#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005233 conn->err_code = CO_ER_SSL_HANDSHAKE;
5234#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005235 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005236#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005237 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5238 empty_handshake = state == TLS_ST_BEFORE;
5239#else
5240 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5241#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005242 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005243 if (!errno) {
5244 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5245 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5246 else
5247 conn->err_code = CO_ER_SSL_EMPTY;
5248 }
5249 else {
5250 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5251 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5252 else
5253 conn->err_code = CO_ER_SSL_ABORT;
5254 }
5255 }
5256 else {
5257 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5258 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005259 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005260 conn->err_code = CO_ER_SSL_HANDSHAKE;
5261 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005262#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005263 }
Emeric Brun674b7432012-11-08 19:21:55 +01005264 goto out_error;
5265 }
5266 else {
5267 /* Fail on all other handshake errors */
5268 /* Note: OpenSSL may leave unread bytes in the socket's
5269 * buffer, causing an RST to be emitted upon close() on
5270 * TCP sockets. We first try to drain possibly pending
5271 * data to avoid this as much as possible.
5272 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005273 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005274 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005275 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5276 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005277 goto out_error;
5278 }
5279 }
5280 /* read some data: consider handshake completed */
5281 goto reneg_ok;
5282 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005283 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005284check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005285 if (ret != 1) {
5286 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005287 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005288
5289 if (ret == SSL_ERROR_WANT_WRITE) {
5290 /* SSL handshake needs to write, L4 connection may not be ready */
5291 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005292 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005293 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005294 return 0;
5295 }
5296 else if (ret == SSL_ERROR_WANT_READ) {
5297 /* SSL handshake needs to read, L4 connection is ready */
5298 if (conn->flags & CO_FL_WAIT_L4_CONN)
5299 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5300 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005301 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005302 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005303 return 0;
5304 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005305#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005306 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005307 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005308 return 0;
5309 }
5310#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005311 else if (ret == SSL_ERROR_SYSCALL) {
5312 /* if errno is null, then connection was successfully established */
5313 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5314 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005315 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005316#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005317 conn->err_code = CO_ER_SSL_HANDSHAKE;
5318#else
5319 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005320#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005321 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5322 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005323#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005324 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005325#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005326 if (empty_handshake) {
5327 if (!errno) {
5328 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5329 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5330 else
5331 conn->err_code = CO_ER_SSL_EMPTY;
5332 }
5333 else {
5334 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5335 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5336 else
5337 conn->err_code = CO_ER_SSL_ABORT;
5338 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005339 }
5340 else {
5341 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5342 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5343 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005344 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005345 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005346#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005347 }
Willy Tarreau89230192012-09-28 20:22:13 +02005348 goto out_error;
5349 }
Emeric Brun46591952012-05-18 15:47:34 +02005350 else {
5351 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005352 /* Note: OpenSSL may leave unread bytes in the socket's
5353 * buffer, causing an RST to be emitted upon close() on
5354 * TCP sockets. We first try to drain possibly pending
5355 * data to avoid this as much as possible.
5356 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005357 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005358 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005359 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5360 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005361 goto out_error;
5362 }
5363 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005364#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5365 else {
5366 /*
5367 * If the server refused the early data, we have to send a
5368 * 425 to the client, as we no longer have the data to sent
5369 * them again.
5370 */
5371 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5372 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5373 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5374 goto out_error;
5375 }
5376 }
5377 }
5378#endif
5379
Emeric Brun46591952012-05-18 15:47:34 +02005380
Emeric Brun674b7432012-11-08 19:21:55 +01005381reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005382
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005383#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005384 /* ASYNC engine API doesn't support moving read/write
5385 * buffers. So we disable ASYNC mode right after
5386 * the handshake to avoid buffer oveflows.
5387 */
5388 if (global_ssl.async)
5389 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5390#endif
Emeric Brun46591952012-05-18 15:47:34 +02005391 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005392 if (!SSL_session_reused(conn->xprt_ctx)) {
5393 if (objt_server(conn->target)) {
5394 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5395 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5396 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005397 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005398 else {
5399 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5400 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5401 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5402 }
Emeric Brun46591952012-05-18 15:47:34 +02005403 }
5404
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005405#ifdef OPENSSL_IS_BORINGSSL
5406 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5407 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5408#endif
Emeric Brun46591952012-05-18 15:47:34 +02005409 /* The connection is now established at both layers, it's time to leave */
5410 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5411 return 1;
5412
5413 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005414 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005415 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005416 ERR_clear_error();
5417
Emeric Brun9fa89732012-10-04 17:09:56 +02005418 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005419 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5420 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5421 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005422 }
5423
Emeric Brun46591952012-05-18 15:47:34 +02005424 /* Fail on all other handshake errors */
5425 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005426 if (!conn->err_code)
5427 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005428 return 0;
5429}
5430
5431/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005432 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005433 * buffer wraps, in which case a second call may be performed. The connection's
5434 * flags are updated with whatever special event is detected (error, read0,
5435 * empty). The caller is responsible for taking care of those events and
5436 * avoiding the call if inappropriate. The function does not call the
5437 * connection's polling update function, so the caller is responsible for this.
5438 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005439static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005440{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005441 ssize_t ret;
5442 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005443
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005444 conn_refresh_polling_flags(conn);
5445
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005446 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005447 goto out_error;
5448
5449 if (conn->flags & CO_FL_HANDSHAKE)
5450 /* a handshake was requested */
5451 return 0;
5452
Emeric Brun46591952012-05-18 15:47:34 +02005453 /* read the largest possible block. For this, we perform only one call
5454 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5455 * in which case we accept to do it once again. A new attempt is made on
5456 * EINTR too.
5457 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005458 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005459 int need_out = 0;
5460
Willy Tarreau591d4452018-06-15 17:21:00 +02005461 try = b_contig_space(buf);
5462 if (!try)
5463 break;
5464
Willy Tarreauabf08d92014-01-14 11:31:27 +01005465 if (try > count)
5466 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005467
Olivier Houchardc2aae742017-09-22 18:26:28 +02005468 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5469 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005470 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005471 done++;
5472 try--;
5473 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005474 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005475 conn->tmp_early_data = -1;
5476 continue;
5477 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005478
Olivier Houchardc2aae742017-09-22 18:26:28 +02005479#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5480 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5481 size_t read_length;
5482
5483 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005484 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005485 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5486 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005487 conn->flags |= CO_FL_EARLY_DATA;
5488 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5489 ret == SSL_READ_EARLY_DATA_FINISH) {
5490 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5491 /*
5492 * We're done reading the early data,
5493 * let's make the handshake
5494 */
5495 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5496 conn->flags |= CO_FL_SSL_WAIT_HS;
5497 need_out = 1;
5498 if (read_length == 0)
5499 break;
5500 }
5501 ret = read_length;
5502 }
5503 } else
5504#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005505 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005506#ifdef OPENSSL_IS_BORINGSSL
5507 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5508 if (SSL_in_early_data(conn->xprt_ctx)) {
5509 if (ret > 0)
5510 conn->flags |= CO_FL_EARLY_DATA;
5511 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005512 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005513 }
5514 }
5515#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005516 if (conn->flags & CO_FL_ERROR) {
5517 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005518 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005519 }
Emeric Brun46591952012-05-18 15:47:34 +02005520 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005521 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005522 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005523 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005524 }
Emeric Brun46591952012-05-18 15:47:34 +02005525 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005526 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005527 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005528 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005529 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005530 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005531#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005532 /* Async mode can be re-enabled, because we're leaving data state.*/
5533 if (global_ssl.async)
5534 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5535#endif
Emeric Brun46591952012-05-18 15:47:34 +02005536 break;
5537 }
5538 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005539 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5540 /* handshake is running, and it may need to re-enable read */
5541 conn->flags |= CO_FL_SSL_WAIT_HS;
5542 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005543#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005544 /* Async mode can be re-enabled, because we're leaving data state.*/
5545 if (global_ssl.async)
5546 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5547#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005548 break;
5549 }
Emeric Brun46591952012-05-18 15:47:34 +02005550 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005551 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005552 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005553 } else if (ret == SSL_ERROR_ZERO_RETURN)
5554 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005555 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5556 * stack before shutting down the connection for
5557 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005558 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5559 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005560 /* otherwise it's a real error */
5561 goto out_error;
5562 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005563 if (need_out)
5564 break;
Emeric Brun46591952012-05-18 15:47:34 +02005565 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005566 leave:
5567 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005568 return done;
5569
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005570 clear_ssl_error:
5571 /* Clear openssl global errors stack */
5572 ssl_sock_dump_errors(conn);
5573 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005574 read0:
5575 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005576 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005577
Emeric Brun46591952012-05-18 15:47:34 +02005578 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005579 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005580 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005581 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005582 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005583 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005584}
5585
5586
Willy Tarreau787db9a2018-06-14 18:31:46 +02005587/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5588 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5589 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005590 * Only one call to send() is performed, unless the buffer wraps, in which case
5591 * a second call may be performed. The connection's flags are updated with
5592 * whatever special event is detected (error, empty). The caller is responsible
5593 * for taking care of those events and avoiding the call if inappropriate. The
5594 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005595 * is responsible for this. The buffer's output is not adjusted, it's up to the
5596 * caller to take care of this. It's up to the caller to update the buffer's
5597 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005598 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005599static 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 +02005600{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005601 ssize_t ret;
5602 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005603
5604 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005605 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005606
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005607 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005608 goto out_error;
5609
5610 if (conn->flags & CO_FL_HANDSHAKE)
5611 /* a handshake was requested */
5612 return 0;
5613
5614 /* send the largest possible block. For this we perform only one call
5615 * to send() unless the buffer wraps and we exactly fill the first hunk,
5616 * in which case we accept to do it once again.
5617 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005618 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005619#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5620 size_t written_data;
5621#endif
5622
Willy Tarreau787db9a2018-06-14 18:31:46 +02005623 try = b_contig_data(buf, done);
5624 if (try > count)
5625 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005626
Willy Tarreau7bed9452014-02-02 02:00:24 +01005627 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005628 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005629 global_ssl.max_record && try > global_ssl.max_record) {
5630 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005631 }
5632 else {
5633 /* we need to keep the information about the fact that
5634 * we're not limiting the upcoming send(), because if it
5635 * fails, we'll have to retry with at least as many data.
5636 */
5637 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5638 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005639
Olivier Houchardc2aae742017-09-22 18:26:28 +02005640#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5641 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5642 unsigned int max_early;
5643
Olivier Houchard522eea72017-11-03 16:27:47 +01005644 if (objt_listener(conn->target))
5645 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5646 else {
5647 if (SSL_get0_session(conn->xprt_ctx))
5648 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5649 else
5650 max_early = 0;
5651 }
5652
Olivier Houchard90084a12017-11-23 18:21:29 +01005653 if (try + conn->sent_early_data > max_early) {
5654 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005655 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005656 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5657 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005658 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005659 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005660 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005661 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005662 if (ret == 1) {
5663 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005664 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005665 if (objt_server(conn->target)) {
5666 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5667 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5668 }
5669
Olivier Houchardc2aae742017-09-22 18:26:28 +02005670 }
5671
5672 } else
5673#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005674 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005675
Emeric Brune1f38db2012-09-03 20:36:47 +02005676 if (conn->flags & CO_FL_ERROR) {
5677 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005678 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005679 }
Emeric Brun46591952012-05-18 15:47:34 +02005680 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005681 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005682 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005683 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005684 }
5685 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005686 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005687
Emeric Brun46591952012-05-18 15:47:34 +02005688 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005689 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5690 /* handshake is running, and it may need to re-enable write */
5691 conn->flags |= CO_FL_SSL_WAIT_HS;
5692 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005693#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005694 /* Async mode can be re-enabled, because we're leaving data state.*/
5695 if (global_ssl.async)
5696 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5697#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005698 break;
5699 }
Emeric Brun46591952012-05-18 15:47:34 +02005700 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005701 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005702 break;
5703 }
5704 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005705 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005706 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005707 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005708#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005709 /* Async mode can be re-enabled, because we're leaving data state.*/
5710 if (global_ssl.async)
5711 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5712#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005713 break;
5714 }
Emeric Brun46591952012-05-18 15:47:34 +02005715 goto out_error;
5716 }
5717 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005718 leave:
5719 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005720 return done;
5721
5722 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005723 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005724 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005725 ERR_clear_error();
5726
Emeric Brun46591952012-05-18 15:47:34 +02005727 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005728 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005729}
5730
Emeric Brun46591952012-05-18 15:47:34 +02005731static void ssl_sock_close(struct connection *conn) {
5732
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005733 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005734#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005735 if (global_ssl.async) {
5736 OSSL_ASYNC_FD all_fd[32], afd;
5737 size_t num_all_fds = 0;
5738 int i;
5739
5740 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5741 if (num_all_fds > 32) {
5742 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5743 return;
5744 }
5745
5746 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5747
5748 /* If an async job is pending, we must try to
5749 to catch the end using polling before calling
5750 SSL_free */
5751 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5752 for (i=0 ; i < num_all_fds ; i++) {
5753 /* switch on an handler designed to
5754 * handle the SSL_free
5755 */
5756 afd = all_fd[i];
5757 fdtab[afd].iocb = ssl_async_fd_free;
5758 fdtab[afd].owner = conn->xprt_ctx;
5759 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005760 /* To ensure that the fd cache won't be used
5761 * and we'll catch a real RD event.
5762 */
5763 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005764 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005765 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005766 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005767 return;
5768 }
Emeric Brun3854e012017-05-17 20:42:48 +02005769 /* Else we can remove the fds from the fdtab
5770 * and call SSL_free.
5771 * note: we do a fd_remove and not a delete
5772 * because the fd is owned by the engine.
5773 * the engine is responsible to close
5774 */
5775 for (i=0 ; i < num_all_fds ; i++)
5776 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005777 }
5778#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005779 SSL_free(conn->xprt_ctx);
5780 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005781 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005782 }
Emeric Brun46591952012-05-18 15:47:34 +02005783}
5784
5785/* This function tries to perform a clean shutdown on an SSL connection, and in
5786 * any case, flags the connection as reusable if no handshake was in progress.
5787 */
5788static void ssl_sock_shutw(struct connection *conn, int clean)
5789{
5790 if (conn->flags & CO_FL_HANDSHAKE)
5791 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005792 if (!clean)
5793 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005794 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005795 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005796 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005797 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005798 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005799 ERR_clear_error();
5800 }
Emeric Brun46591952012-05-18 15:47:34 +02005801}
5802
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005803/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005804int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005805{
5806 struct pkey_info *pkinfo;
5807 int bits = 0;
5808 int sig = TLSEXT_signature_anonymous;
5809 int len = -1;
5810
5811 if (!ssl_sock_is_ssl(conn))
5812 return 0;
5813
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005814 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005815 if (pkinfo) {
5816 sig = pkinfo->sig;
5817 bits = pkinfo->bits;
5818 } else {
5819 /* multicert and generated cert have no pkey info */
5820 X509 *crt;
5821 EVP_PKEY *pkey;
5822 crt = SSL_get_certificate(conn->xprt_ctx);
5823 if (!crt)
5824 return 0;
5825 pkey = X509_get_pubkey(crt);
5826 if (pkey) {
5827 bits = EVP_PKEY_bits(pkey);
5828 switch(EVP_PKEY_base_id(pkey)) {
5829 case EVP_PKEY_RSA:
5830 sig = TLSEXT_signature_rsa;
5831 break;
5832 case EVP_PKEY_EC:
5833 sig = TLSEXT_signature_ecdsa;
5834 break;
5835 case EVP_PKEY_DSA:
5836 sig = TLSEXT_signature_dsa;
5837 break;
5838 }
5839 EVP_PKEY_free(pkey);
5840 }
5841 }
5842
5843 switch(sig) {
5844 case TLSEXT_signature_rsa:
5845 len = chunk_printf(out, "RSA%d", bits);
5846 break;
5847 case TLSEXT_signature_ecdsa:
5848 len = chunk_printf(out, "EC%d", bits);
5849 break;
5850 case TLSEXT_signature_dsa:
5851 len = chunk_printf(out, "DSA%d", bits);
5852 break;
5853 default:
5854 return 0;
5855 }
5856 if (len < 0)
5857 return 0;
5858 return 1;
5859}
5860
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005861/* used for ppv2 cert signature (can be used for logging) */
5862const char *ssl_sock_get_cert_sig(struct connection *conn)
5863{
5864 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5865 X509 *crt;
5866
5867 if (!ssl_sock_is_ssl(conn))
5868 return NULL;
5869 crt = SSL_get_certificate(conn->xprt_ctx);
5870 if (!crt)
5871 return NULL;
5872 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5873 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5874}
5875
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005876/* used for ppv2 authority */
5877const char *ssl_sock_get_sni(struct connection *conn)
5878{
5879#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5880 if (!ssl_sock_is_ssl(conn))
5881 return NULL;
5882 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5883#else
5884 return 0;
5885#endif
5886}
5887
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005888/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005889const char *ssl_sock_get_cipher_name(struct connection *conn)
5890{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005891 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005892 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005893
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005894 return SSL_get_cipher_name(conn->xprt_ctx);
5895}
5896
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005897/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005898const char *ssl_sock_get_proto_version(struct connection *conn)
5899{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005900 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005901 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005902
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005903 return SSL_get_version(conn->xprt_ctx);
5904}
5905
Willy Tarreau8d598402012-10-22 17:58:39 +02005906/* Extract a serial from a cert, and copy it to a chunk.
5907 * Returns 1 if serial is found and copied, 0 if no serial found and
5908 * -1 if output is not large enough.
5909 */
5910static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005911ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005912{
5913 ASN1_INTEGER *serial;
5914
5915 serial = X509_get_serialNumber(crt);
5916 if (!serial)
5917 return 0;
5918
5919 if (out->size < serial->length)
5920 return -1;
5921
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005922 memcpy(out->area, serial->data, serial->length);
5923 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005924 return 1;
5925}
5926
Emeric Brun43e79582014-10-29 19:03:26 +01005927/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005928 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5929 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005930 */
5931static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005932ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005933{
5934 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005935 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005936
5937 len =i2d_X509(crt, NULL);
5938 if (len <= 0)
5939 return 1;
5940
5941 if (out->size < len)
5942 return -1;
5943
5944 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005945 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005946 return 1;
5947}
5948
Emeric Brunce5ad802012-10-22 14:11:22 +02005949
Willy Tarreau83061a82018-07-13 11:56:34 +02005950/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005951 * Returns 1 if serial is found and copied, 0 if no valid time found
5952 * and -1 if output is not large enough.
5953 */
5954static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005955ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005956{
5957 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5958 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5959
5960 if (gentm->length < 12)
5961 return 0;
5962 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5963 return 0;
5964 if (out->size < gentm->length-2)
5965 return -1;
5966
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005967 memcpy(out->area, gentm->data+2, gentm->length-2);
5968 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005969 return 1;
5970 }
5971 else if (tm->type == V_ASN1_UTCTIME) {
5972 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5973
5974 if (utctm->length < 10)
5975 return 0;
5976 if (utctm->data[0] >= 0x35)
5977 return 0;
5978 if (out->size < utctm->length)
5979 return -1;
5980
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005981 memcpy(out->area, utctm->data, utctm->length);
5982 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005983 return 1;
5984 }
5985
5986 return 0;
5987}
5988
Emeric Brun87855892012-10-17 17:39:35 +02005989/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5990 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5991 */
5992static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005993ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5994 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005995{
5996 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005997 ASN1_OBJECT *obj;
5998 ASN1_STRING *data;
5999 const unsigned char *data_ptr;
6000 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006001 int i, j, n;
6002 int cur = 0;
6003 const char *s;
6004 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006005 int name_count;
6006
6007 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006008
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006009 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006010 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006011 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006012 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006013 else
6014 j = i;
6015
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006016 ne = X509_NAME_get_entry(a, j);
6017 obj = X509_NAME_ENTRY_get_object(ne);
6018 data = X509_NAME_ENTRY_get_data(ne);
6019 data_ptr = ASN1_STRING_get0_data(data);
6020 data_len = ASN1_STRING_length(data);
6021 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006022 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006023 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006024 s = tmp;
6025 }
6026
6027 if (chunk_strcasecmp(entry, s) != 0)
6028 continue;
6029
6030 if (pos < 0)
6031 cur--;
6032 else
6033 cur++;
6034
6035 if (cur != pos)
6036 continue;
6037
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006038 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006039 return -1;
6040
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006041 memcpy(out->area, data_ptr, data_len);
6042 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006043 return 1;
6044 }
6045
6046 return 0;
6047
6048}
6049
6050/* Extract and format full DN from a X509_NAME and copy result into a chunk
6051 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6052 */
6053static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006054ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006055{
6056 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006057 ASN1_OBJECT *obj;
6058 ASN1_STRING *data;
6059 const unsigned char *data_ptr;
6060 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006061 int i, n, ln;
6062 int l = 0;
6063 const char *s;
6064 char *p;
6065 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006066 int name_count;
6067
6068
6069 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006070
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006071 out->data = 0;
6072 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006073 for (i = 0; i < name_count; i++) {
6074 ne = X509_NAME_get_entry(a, i);
6075 obj = X509_NAME_ENTRY_get_object(ne);
6076 data = X509_NAME_ENTRY_get_data(ne);
6077 data_ptr = ASN1_STRING_get0_data(data);
6078 data_len = ASN1_STRING_length(data);
6079 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006080 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006081 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006082 s = tmp;
6083 }
6084 ln = strlen(s);
6085
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006086 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006087 if (l > out->size)
6088 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006089 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006090
6091 *(p++)='/';
6092 memcpy(p, s, ln);
6093 p += ln;
6094 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006095 memcpy(p, data_ptr, data_len);
6096 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006097 }
6098
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006099 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006100 return 0;
6101
6102 return 1;
6103}
6104
Willy Tarreau119a4082016-12-22 21:58:38 +01006105/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6106 * to disable SNI.
6107 */
Willy Tarreau63076412015-07-10 11:33:32 +02006108void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6109{
6110#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006111 char *prev_name;
6112
Willy Tarreau63076412015-07-10 11:33:32 +02006113 if (!ssl_sock_is_ssl(conn))
6114 return;
6115
Willy Tarreau119a4082016-12-22 21:58:38 +01006116 /* if the SNI changes, we must destroy the reusable context so that a
6117 * new connection will present a new SNI. As an optimization we could
6118 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6119 * server.
6120 */
6121 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6122 if ((!prev_name && hostname) ||
6123 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6124 SSL_set_session(conn->xprt_ctx, NULL);
6125
Willy Tarreau63076412015-07-10 11:33:32 +02006126 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6127#endif
6128}
6129
Emeric Brun0abf8362014-06-24 18:26:41 +02006130/* Extract peer certificate's common name into the chunk dest
6131 * Returns
6132 * the len of the extracted common name
6133 * or 0 if no CN found in DN
6134 * or -1 on error case (i.e. no peer certificate)
6135 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006136int ssl_sock_get_remote_common_name(struct connection *conn,
6137 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006138{
6139 X509 *crt = NULL;
6140 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006141 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006142 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006143 .area = (char *)&find_cn,
6144 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006145 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006146 int result = -1;
David Safb76832014-05-08 23:42:08 -04006147
6148 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006149 goto out;
David Safb76832014-05-08 23:42:08 -04006150
6151 /* SSL_get_peer_certificate, it increase X509 * ref count */
6152 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6153 if (!crt)
6154 goto out;
6155
6156 name = X509_get_subject_name(crt);
6157 if (!name)
6158 goto out;
David Safb76832014-05-08 23:42:08 -04006159
Emeric Brun0abf8362014-06-24 18:26:41 +02006160 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6161out:
David Safb76832014-05-08 23:42:08 -04006162 if (crt)
6163 X509_free(crt);
6164
6165 return result;
6166}
6167
Dave McCowan328fb582014-07-30 10:39:13 -04006168/* returns 1 if client passed a certificate for this session, 0 if not */
6169int ssl_sock_get_cert_used_sess(struct connection *conn)
6170{
6171 X509 *crt = NULL;
6172
6173 if (!ssl_sock_is_ssl(conn))
6174 return 0;
6175
6176 /* SSL_get_peer_certificate, it increase X509 * ref count */
6177 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6178 if (!crt)
6179 return 0;
6180
6181 X509_free(crt);
6182 return 1;
6183}
6184
6185/* returns 1 if client passed a certificate for this connection, 0 if not */
6186int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006187{
6188 if (!ssl_sock_is_ssl(conn))
6189 return 0;
6190
6191 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6192}
6193
6194/* returns result from SSL verify */
6195unsigned int ssl_sock_get_verify_result(struct connection *conn)
6196{
6197 if (!ssl_sock_is_ssl(conn))
6198 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6199
6200 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6201}
6202
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006203/* Returns the application layer protocol name in <str> and <len> when known.
6204 * Zero is returned if the protocol name was not found, otherwise non-zero is
6205 * returned. The string is allocated in the SSL context and doesn't have to be
6206 * freed by the caller. NPN is also checked if available since older versions
6207 * of openssl (1.0.1) which are more common in field only support this one.
6208 */
6209static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6210{
6211 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6212 return 0;
6213
6214 *str = NULL;
6215
6216#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6217 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6218 if (*str)
6219 return 1;
6220#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006221#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006222 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6223 if (*str)
6224 return 1;
6225#endif
6226 return 0;
6227}
6228
Willy Tarreau7875d092012-09-10 08:20:03 +02006229/***** Below are some sample fetching functions for ACL/patterns *****/
6230
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006231static int
6232smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6233{
6234 struct connection *conn;
6235
6236 conn = objt_conn(smp->sess->origin);
6237 if (!conn || conn->xprt != &ssl_sock)
6238 return 0;
6239
6240 smp->flags = 0;
6241 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006242 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6243 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006244
6245 return 1;
6246}
6247
Emeric Brune64aef12012-09-21 13:15:06 +02006248/* boolean, returns true if client cert was present */
6249static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006250smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006251{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006252 struct connection *conn;
6253
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006254 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006255 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006256 return 0;
6257
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006258 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006259 smp->flags |= SMP_F_MAY_CHANGE;
6260 return 0;
6261 }
6262
6263 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006264 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006265 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006266
6267 return 1;
6268}
6269
Emeric Brun43e79582014-10-29 19:03:26 +01006270/* binary, returns a certificate in a binary chunk (der/raw).
6271 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6272 * should be use.
6273 */
6274static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006275smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006276{
6277 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6278 X509 *crt = NULL;
6279 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006280 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006281 struct connection *conn;
6282
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006283 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006284 if (!conn || conn->xprt != &ssl_sock)
6285 return 0;
6286
6287 if (!(conn->flags & CO_FL_CONNECTED)) {
6288 smp->flags |= SMP_F_MAY_CHANGE;
6289 return 0;
6290 }
6291
6292 if (cert_peer)
6293 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6294 else
6295 crt = SSL_get_certificate(conn->xprt_ctx);
6296
6297 if (!crt)
6298 goto out;
6299
6300 smp_trash = get_trash_chunk();
6301 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6302 goto out;
6303
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006304 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006305 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006306 ret = 1;
6307out:
6308 /* SSL_get_peer_certificate, it increase X509 * ref count */
6309 if (cert_peer && crt)
6310 X509_free(crt);
6311 return ret;
6312}
6313
Emeric Brunba841a12014-04-30 17:05:08 +02006314/* binary, returns serial of certificate in a binary chunk.
6315 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6316 * should be use.
6317 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006318static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006319smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006320{
Emeric Brunba841a12014-04-30 17:05:08 +02006321 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006322 X509 *crt = NULL;
6323 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006324 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006325 struct connection *conn;
6326
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006327 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006328 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006329 return 0;
6330
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006331 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006332 smp->flags |= SMP_F_MAY_CHANGE;
6333 return 0;
6334 }
6335
Emeric Brunba841a12014-04-30 17:05:08 +02006336 if (cert_peer)
6337 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6338 else
6339 crt = SSL_get_certificate(conn->xprt_ctx);
6340
Willy Tarreau8d598402012-10-22 17:58:39 +02006341 if (!crt)
6342 goto out;
6343
Willy Tarreau47ca5452012-12-23 20:22:19 +01006344 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006345 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6346 goto out;
6347
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006348 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006349 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006350 ret = 1;
6351out:
Emeric Brunba841a12014-04-30 17:05:08 +02006352 /* SSL_get_peer_certificate, it increase X509 * ref count */
6353 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006354 X509_free(crt);
6355 return ret;
6356}
Emeric Brune64aef12012-09-21 13:15:06 +02006357
Emeric Brunba841a12014-04-30 17:05:08 +02006358/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6359 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6360 * should be use.
6361 */
James Votha051b4a2013-05-14 20:37:59 +02006362static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006363smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006364{
Emeric Brunba841a12014-04-30 17:05:08 +02006365 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006366 X509 *crt = NULL;
6367 const EVP_MD *digest;
6368 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006369 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006370 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006371
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006372 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006373 if (!conn || conn->xprt != &ssl_sock)
6374 return 0;
6375
6376 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006377 smp->flags |= SMP_F_MAY_CHANGE;
6378 return 0;
6379 }
6380
Emeric Brunba841a12014-04-30 17:05:08 +02006381 if (cert_peer)
6382 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6383 else
6384 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006385 if (!crt)
6386 goto out;
6387
6388 smp_trash = get_trash_chunk();
6389 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006390 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6391 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006392
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006393 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006394 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006395 ret = 1;
6396out:
Emeric Brunba841a12014-04-30 17:05:08 +02006397 /* SSL_get_peer_certificate, it increase X509 * ref count */
6398 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006399 X509_free(crt);
6400 return ret;
6401}
6402
Emeric Brunba841a12014-04-30 17:05:08 +02006403/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6404 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6405 * should be use.
6406 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006407static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006408smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006409{
Emeric Brunba841a12014-04-30 17:05:08 +02006410 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006411 X509 *crt = NULL;
6412 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006413 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006414 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006415
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006416 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006417 if (!conn || conn->xprt != &ssl_sock)
6418 return 0;
6419
6420 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006421 smp->flags |= SMP_F_MAY_CHANGE;
6422 return 0;
6423 }
6424
Emeric Brunba841a12014-04-30 17:05:08 +02006425 if (cert_peer)
6426 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6427 else
6428 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006429 if (!crt)
6430 goto out;
6431
Willy Tarreau47ca5452012-12-23 20:22:19 +01006432 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006433 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006434 goto out;
6435
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006436 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006437 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006438 ret = 1;
6439out:
Emeric Brunba841a12014-04-30 17:05:08 +02006440 /* SSL_get_peer_certificate, it increase X509 * ref count */
6441 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006442 X509_free(crt);
6443 return ret;
6444}
6445
Emeric Brunba841a12014-04-30 17:05:08 +02006446/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6447 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6448 * should be use.
6449 */
Emeric Brun87855892012-10-17 17:39:35 +02006450static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006451smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006452{
Emeric Brunba841a12014-04-30 17:05:08 +02006453 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006454 X509 *crt = NULL;
6455 X509_NAME *name;
6456 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006457 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006458 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006459
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006460 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006461 if (!conn || conn->xprt != &ssl_sock)
6462 return 0;
6463
6464 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006465 smp->flags |= SMP_F_MAY_CHANGE;
6466 return 0;
6467 }
6468
Emeric Brunba841a12014-04-30 17:05:08 +02006469 if (cert_peer)
6470 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6471 else
6472 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006473 if (!crt)
6474 goto out;
6475
6476 name = X509_get_issuer_name(crt);
6477 if (!name)
6478 goto out;
6479
Willy Tarreau47ca5452012-12-23 20:22:19 +01006480 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006481 if (args && args[0].type == ARGT_STR) {
6482 int pos = 1;
6483
6484 if (args[1].type == ARGT_SINT)
6485 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006486
6487 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6488 goto out;
6489 }
6490 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6491 goto out;
6492
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006493 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006494 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006495 ret = 1;
6496out:
Emeric Brunba841a12014-04-30 17:05:08 +02006497 /* SSL_get_peer_certificate, it increase X509 * ref count */
6498 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006499 X509_free(crt);
6500 return ret;
6501}
6502
Emeric Brunba841a12014-04-30 17:05:08 +02006503/* string, returns notbefore date in ASN1_UTCTIME format.
6504 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6505 * should be use.
6506 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006507static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006508smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006509{
Emeric Brunba841a12014-04-30 17:05:08 +02006510 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006511 X509 *crt = NULL;
6512 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006513 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006514 struct connection *conn;
6515
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006516 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006517 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006518 return 0;
6519
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006520 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006521 smp->flags |= SMP_F_MAY_CHANGE;
6522 return 0;
6523 }
6524
Emeric Brunba841a12014-04-30 17:05:08 +02006525 if (cert_peer)
6526 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6527 else
6528 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006529 if (!crt)
6530 goto out;
6531
Willy Tarreau47ca5452012-12-23 20:22:19 +01006532 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006533 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006534 goto out;
6535
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006536 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006537 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006538 ret = 1;
6539out:
Emeric Brunba841a12014-04-30 17:05:08 +02006540 /* SSL_get_peer_certificate, it increase X509 * ref count */
6541 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006542 X509_free(crt);
6543 return ret;
6544}
6545
Emeric Brunba841a12014-04-30 17:05:08 +02006546/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6547 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6548 * should be use.
6549 */
Emeric Brun87855892012-10-17 17:39:35 +02006550static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006551smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006552{
Emeric Brunba841a12014-04-30 17:05:08 +02006553 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006554 X509 *crt = NULL;
6555 X509_NAME *name;
6556 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006557 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006558 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006559
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006560 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006561 if (!conn || conn->xprt != &ssl_sock)
6562 return 0;
6563
6564 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006565 smp->flags |= SMP_F_MAY_CHANGE;
6566 return 0;
6567 }
6568
Emeric Brunba841a12014-04-30 17:05:08 +02006569 if (cert_peer)
6570 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6571 else
6572 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006573 if (!crt)
6574 goto out;
6575
6576 name = X509_get_subject_name(crt);
6577 if (!name)
6578 goto out;
6579
Willy Tarreau47ca5452012-12-23 20:22:19 +01006580 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006581 if (args && args[0].type == ARGT_STR) {
6582 int pos = 1;
6583
6584 if (args[1].type == ARGT_SINT)
6585 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006586
6587 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6588 goto out;
6589 }
6590 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6591 goto out;
6592
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006593 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006594 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006595 ret = 1;
6596out:
Emeric Brunba841a12014-04-30 17:05:08 +02006597 /* SSL_get_peer_certificate, it increase X509 * ref count */
6598 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006599 X509_free(crt);
6600 return ret;
6601}
Emeric Brun9143d372012-12-20 15:44:16 +01006602
6603/* integer, returns true if current session use a client certificate */
6604static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006605smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006606{
6607 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006608 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006609
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006610 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006611 if (!conn || conn->xprt != &ssl_sock)
6612 return 0;
6613
6614 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006615 smp->flags |= SMP_F_MAY_CHANGE;
6616 return 0;
6617 }
6618
6619 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006620 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006621 if (crt) {
6622 X509_free(crt);
6623 }
6624
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006625 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006626 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006627 return 1;
6628}
6629
Emeric Brunba841a12014-04-30 17:05:08 +02006630/* integer, returns the certificate version
6631 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6632 * should be use.
6633 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006634static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006635smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006636{
Emeric Brunba841a12014-04-30 17:05:08 +02006637 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006638 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006639 struct connection *conn;
6640
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006641 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006642 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006643 return 0;
6644
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006645 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006646 smp->flags |= SMP_F_MAY_CHANGE;
6647 return 0;
6648 }
6649
Emeric Brunba841a12014-04-30 17:05:08 +02006650 if (cert_peer)
6651 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6652 else
6653 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006654 if (!crt)
6655 return 0;
6656
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006657 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006658 /* SSL_get_peer_certificate increase X509 * ref count */
6659 if (cert_peer)
6660 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006661 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006662
6663 return 1;
6664}
6665
Emeric Brunba841a12014-04-30 17:05:08 +02006666/* string, returns the certificate's signature algorithm.
6667 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6668 * should be use.
6669 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006670static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006671smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006672{
Emeric Brunba841a12014-04-30 17:05:08 +02006673 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006674 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006675 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006676 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006677 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006678
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006679 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006680 if (!conn || conn->xprt != &ssl_sock)
6681 return 0;
6682
6683 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006684 smp->flags |= SMP_F_MAY_CHANGE;
6685 return 0;
6686 }
6687
Emeric Brunba841a12014-04-30 17:05:08 +02006688 if (cert_peer)
6689 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6690 else
6691 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006692 if (!crt)
6693 return 0;
6694
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006695 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6696 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006697
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006698 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6699 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006700 /* SSL_get_peer_certificate increase X509 * ref count */
6701 if (cert_peer)
6702 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006703 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006704 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006705
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006706 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006707 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006708 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006709 /* SSL_get_peer_certificate increase X509 * ref count */
6710 if (cert_peer)
6711 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006712
6713 return 1;
6714}
6715
Emeric Brunba841a12014-04-30 17:05:08 +02006716/* string, returns the certificate's key algorithm.
6717 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6718 * should be use.
6719 */
Emeric Brun521a0112012-10-22 12:22:55 +02006720static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006721smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006722{
Emeric Brunba841a12014-04-30 17:05:08 +02006723 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006724 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006725 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006726 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006727 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006728
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006729 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006730 if (!conn || conn->xprt != &ssl_sock)
6731 return 0;
6732
6733 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006734 smp->flags |= SMP_F_MAY_CHANGE;
6735 return 0;
6736 }
6737
Emeric Brunba841a12014-04-30 17:05:08 +02006738 if (cert_peer)
6739 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6740 else
6741 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006742 if (!crt)
6743 return 0;
6744
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006745 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6746 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006747
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006748 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6749 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006750 /* SSL_get_peer_certificate increase X509 * ref count */
6751 if (cert_peer)
6752 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006753 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006754 }
Emeric Brun521a0112012-10-22 12:22:55 +02006755
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006756 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006757 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006758 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006759 if (cert_peer)
6760 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006761
6762 return 1;
6763}
6764
Emeric Brun645ae792014-04-30 14:21:06 +02006765/* boolean, returns true if front conn. transport layer is SSL.
6766 * This function is also usable on backend conn if the fetch keyword 5th
6767 * char is 'b'.
6768 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006769static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006770smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006771{
Emeric Bruneb8def92018-02-19 15:59:48 +01006772 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6773 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006774
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006775 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006776 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006777 return 1;
6778}
6779
Emeric Brun2525b6b2012-10-18 15:59:43 +02006780/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006781static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006782smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006783{
6784#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006785 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006786
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006787 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006788 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006789 conn->xprt_ctx &&
6790 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006791 return 1;
6792#else
6793 return 0;
6794#endif
6795}
6796
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006797/* boolean, returns true if client session has been resumed.
6798 * This function is also usable on backend conn if the fetch keyword 5th
6799 * char is 'b'.
6800 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006801static int
6802smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6803{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006804 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6805 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6806
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006807
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006808 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006809 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006810 conn->xprt_ctx &&
6811 SSL_session_reused(conn->xprt_ctx);
6812 return 1;
6813}
6814
Emeric Brun645ae792014-04-30 14:21:06 +02006815/* string, returns the used cipher if front conn. transport layer is SSL.
6816 * This function is also usable on backend conn if the fetch keyword 5th
6817 * char is 'b'.
6818 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006819static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006820smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006821{
Emeric Bruneb8def92018-02-19 15:59:48 +01006822 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6823 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006824
Willy Tarreaube508f12016-03-10 11:47:01 +01006825 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006826 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006827 return 0;
6828
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006829 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6830 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006831 return 0;
6832
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006833 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006834 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006835 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006836
6837 return 1;
6838}
6839
Emeric Brun645ae792014-04-30 14:21:06 +02006840/* integer, returns the algoritm's keysize if front conn. transport layer
6841 * is SSL.
6842 * This function is also usable on backend conn if the fetch keyword 5th
6843 * char is 'b'.
6844 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006845static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006846smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006847{
Emeric Bruneb8def92018-02-19 15:59:48 +01006848 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6849 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006850 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006851
Emeric Brun589fcad2012-10-16 14:13:26 +02006852 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006853 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006854 return 0;
6855
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006856 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006857 return 0;
6858
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006859 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006860 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006861
6862 return 1;
6863}
6864
Emeric Brun645ae792014-04-30 14:21:06 +02006865/* integer, returns the used keysize if front conn. transport layer is SSL.
6866 * This function is also usable on backend conn if the fetch keyword 5th
6867 * char is 'b'.
6868 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006869static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006870smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006871{
Emeric Bruneb8def92018-02-19 15:59:48 +01006872 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6873 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006874
Emeric Brun589fcad2012-10-16 14:13:26 +02006875 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006876 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6877 return 0;
6878
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006879 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6880 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006881 return 0;
6882
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006883 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006884
6885 return 1;
6886}
6887
Bernard Spil13c53f82018-02-15 13:34:58 +01006888#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006889static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006890smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006891{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006892 struct connection *conn;
6893
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006894 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006895 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006896
Olivier Houchard6b77f492018-11-22 18:18:29 +01006897 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6898 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6900 return 0;
6901
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006902 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006903 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006904 (const unsigned char **)&smp->data.u.str.area,
6905 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006906
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006907 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006908 return 0;
6909
6910 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006911}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006912#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006913
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006914#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006915static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006916smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006917{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006918 struct connection *conn;
6919
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006920 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006921 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006922
Olivier Houchard6b77f492018-11-22 18:18:29 +01006923 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6924 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6925
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006926 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006927 return 0;
6928
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006929 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006930 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006931 (const unsigned char **)&smp->data.u.str.area,
6932 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006933
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006934 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006935 return 0;
6936
6937 return 1;
6938}
6939#endif
6940
Emeric Brun645ae792014-04-30 14:21:06 +02006941/* string, returns the used protocol if front conn. transport layer is SSL.
6942 * This function is also usable on backend conn if the fetch keyword 5th
6943 * char is 'b'.
6944 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006945static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006946smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006947{
Emeric Bruneb8def92018-02-19 15:59:48 +01006948 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6949 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006950
Emeric Brun589fcad2012-10-16 14:13:26 +02006951 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006952 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6953 return 0;
6954
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006955 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6956 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006957 return 0;
6958
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006959 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006960 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006961 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006962
6963 return 1;
6964}
6965
Willy Tarreau87b09662015-04-03 00:22:06 +02006966/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006967 * This function is also usable on backend conn if the fetch keyword 5th
6968 * char is 'b'.
6969 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006970#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006971static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006972smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006973{
Emeric Bruneb8def92018-02-19 15:59:48 +01006974 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6975 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006976 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006977
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006978 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006979 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006980
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006981 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6982 return 0;
6983
Willy Tarreau192252e2015-04-04 01:47:55 +02006984 ssl_sess = SSL_get_session(conn->xprt_ctx);
6985 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006986 return 0;
6987
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006988 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6989 (unsigned int *)&smp->data.u.str.data);
6990 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006991 return 0;
6992
6993 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006994}
Patrick Hemmer41966772018-04-28 19:15:48 -04006995#endif
6996
Emeric Brunfe68f682012-10-16 14:59:28 +02006997
Patrick Hemmere0275472018-04-28 19:15:51 -04006998#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6999static int
7000smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7001{
7002 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7003 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7004 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007005 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04007006
7007 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7008 return 0;
7009
7010 ssl_sess = SSL_get_session(conn->xprt_ctx);
7011 if (!ssl_sess)
7012 return 0;
7013
7014 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007015 data->data = SSL_SESSION_get_master_key(ssl_sess,
7016 (unsigned char *) data->area,
7017 data->size);
7018 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007019 return 0;
7020
7021 smp->flags = 0;
7022 smp->data.type = SMP_T_BIN;
7023 smp->data.u.str = *data;
7024
7025 return 1;
7026}
7027#endif
7028
Patrick Hemmer41966772018-04-28 19:15:48 -04007029#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007030static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007031smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007032{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007033 struct connection *conn;
7034
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007035 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007036 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007037
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007038 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007039 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7040 return 0;
7041
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007042 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7043 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007044 return 0;
7045
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007046 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007047 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007048}
Patrick Hemmer41966772018-04-28 19:15:48 -04007049#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007050
David Sc1ad52e2014-04-08 18:48:47 -04007051static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007052smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7053{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007054 struct connection *conn;
7055 struct ssl_capture *capture;
7056
7057 conn = objt_conn(smp->sess->origin);
7058 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7059 return 0;
7060
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007061 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007062 if (!capture)
7063 return 0;
7064
7065 smp->flags = SMP_F_CONST;
7066 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007067 smp->data.u.str.area = capture->ciphersuite;
7068 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007069 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007070}
7071
7072static int
7073smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7074{
Willy Tarreau83061a82018-07-13 11:56:34 +02007075 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007076
7077 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7078 return 0;
7079
7080 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007081 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007082 smp->data.type = SMP_T_BIN;
7083 smp->data.u.str = *data;
7084 return 1;
7085}
7086
7087static int
7088smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7089{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007090 struct connection *conn;
7091 struct ssl_capture *capture;
7092
7093 conn = objt_conn(smp->sess->origin);
7094 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7095 return 0;
7096
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007097 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007098 if (!capture)
7099 return 0;
7100
7101 smp->data.type = SMP_T_SINT;
7102 smp->data.u.sint = capture->xxh64;
7103 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007104}
7105
7106static int
7107smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7108{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007109#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007110 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007111 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007112
7113 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7114 return 0;
7115
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007116 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007117 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007118 const char *str;
7119 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007120 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007121 uint16_t id = (bin[0] << 8) | bin[1];
7122#if defined(OPENSSL_IS_BORINGSSL)
7123 cipher = SSL_get_cipher_by_value(id);
7124#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007125 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007126 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7127#endif
7128 str = SSL_CIPHER_get_name(cipher);
7129 if (!str || strcmp(str, "(NONE)") == 0)
7130 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007131 else
7132 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7133 }
7134 smp->data.type = SMP_T_STR;
7135 smp->data.u.str = *data;
7136 return 1;
7137#else
7138 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7139#endif
7140}
7141
Patrick Hemmer41966772018-04-28 19:15:48 -04007142#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007143static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007144smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007145{
Emeric Bruneb8def92018-02-19 15:59:48 +01007146 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7147 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007148 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007149 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007150
7151 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007152 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7153 return 0;
7154
7155 if (!(conn->flags & CO_FL_CONNECTED)) {
7156 smp->flags |= SMP_F_MAY_CHANGE;
7157 return 0;
7158 }
7159
7160 finished_trash = get_trash_chunk();
7161 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007162 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7163 finished_trash->area,
7164 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007165 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007166 finished_len = SSL_get_finished(conn->xprt_ctx,
7167 finished_trash->area,
7168 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007169
7170 if (!finished_len)
7171 return 0;
7172
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007173 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007174 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007175 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007176
7177 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007178}
Patrick Hemmer41966772018-04-28 19:15:48 -04007179#endif
David Sc1ad52e2014-04-08 18:48:47 -04007180
Emeric Brun2525b6b2012-10-18 15:59:43 +02007181/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007182static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007183smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007184{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007185 struct connection *conn;
7186
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007187 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007188 if (!conn || conn->xprt != &ssl_sock)
7189 return 0;
7190
7191 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007192 smp->flags = SMP_F_MAY_CHANGE;
7193 return 0;
7194 }
7195
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007196 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007197 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007198 smp->flags = 0;
7199
7200 return 1;
7201}
7202
Emeric Brun2525b6b2012-10-18 15:59:43 +02007203/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007204static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007205smp_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 +02007206{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007207 struct connection *conn;
7208
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007209 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007211 return 0;
7212
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007213 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007214 smp->flags = SMP_F_MAY_CHANGE;
7215 return 0;
7216 }
7217
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007218 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007219 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007220 smp->flags = 0;
7221
7222 return 1;
7223}
7224
Emeric Brun2525b6b2012-10-18 15:59:43 +02007225/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007226static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007227smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007228{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007229 struct connection *conn;
7230
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007231 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007232 if (!conn || conn->xprt != &ssl_sock)
7233 return 0;
7234
7235 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007236 smp->flags = SMP_F_MAY_CHANGE;
7237 return 0;
7238 }
7239
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007240 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007241 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007242 smp->flags = 0;
7243
7244 return 1;
7245}
7246
Emeric Brun2525b6b2012-10-18 15:59:43 +02007247/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007248static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007249smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007250{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007251 struct connection *conn;
7252
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007253 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007254 if (!conn || conn->xprt != &ssl_sock)
7255 return 0;
7256
7257 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007258 smp->flags = SMP_F_MAY_CHANGE;
7259 return 0;
7260 }
7261
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007262 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007263 return 0;
7264
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007265 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007266 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007267 smp->flags = 0;
7268
7269 return 1;
7270}
7271
Emeric Brunfb510ea2012-10-05 12:00:26 +02007272/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007273static 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 +02007274{
7275 if (!*args[cur_arg + 1]) {
7276 if (err)
7277 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7278 return ERR_ALERT | ERR_FATAL;
7279 }
7280
Willy Tarreauef934602016-12-22 23:12:01 +01007281 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7282 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007283 else
7284 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007285
Emeric Brund94b3fe2012-09-20 18:23:56 +02007286 return 0;
7287}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007288static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7289{
7290 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7291}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007292
Christopher Faulet31af49d2015-06-09 17:29:50 +02007293/* parse the "ca-sign-file" bind keyword */
7294static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7295{
7296 if (!*args[cur_arg + 1]) {
7297 if (err)
7298 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7299 return ERR_ALERT | ERR_FATAL;
7300 }
7301
Willy Tarreauef934602016-12-22 23:12:01 +01007302 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7303 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007304 else
7305 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7306
7307 return 0;
7308}
7309
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007310/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007311static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7312{
7313 if (!*args[cur_arg + 1]) {
7314 if (err)
7315 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7316 return ERR_ALERT | ERR_FATAL;
7317 }
7318 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7319 return 0;
7320}
7321
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007322/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007323static 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 +02007324{
7325 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007326 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007327 return ERR_ALERT | ERR_FATAL;
7328 }
7329
Emeric Brun76d88952012-10-05 15:47:31 +02007330 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007331 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007332 return 0;
7333}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007334static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7335{
7336 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7337}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007338
7339#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7340/* parse the "ciphersuites" bind keyword */
7341static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7342{
7343 if (!*args[cur_arg + 1]) {
7344 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7345 return ERR_ALERT | ERR_FATAL;
7346 }
7347
7348 free(conf->ciphersuites);
7349 conf->ciphersuites = strdup(args[cur_arg + 1]);
7350 return 0;
7351}
7352static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7353{
7354 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7355}
7356#endif
7357
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007358/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007359static 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 +02007360{
Willy Tarreau38011032013-08-13 16:59:39 +02007361 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007362
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007363 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007364 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007365 return ERR_ALERT | ERR_FATAL;
7366 }
7367
Willy Tarreauef934602016-12-22 23:12:01 +01007368 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7369 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007370 memprintf(err, "'%s' : path too long", args[cur_arg]);
7371 return ERR_ALERT | ERR_FATAL;
7372 }
Willy Tarreauef934602016-12-22 23:12:01 +01007373 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007374 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007375 return ERR_ALERT | ERR_FATAL;
7376
7377 return 0;
7378 }
7379
Willy Tarreau03209342016-12-22 17:08:28 +01007380 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007381 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007382
7383 return 0;
7384}
7385
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007386/* parse the "crt-list" bind keyword */
7387static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7388{
7389 if (!*args[cur_arg + 1]) {
7390 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7391 return ERR_ALERT | ERR_FATAL;
7392 }
7393
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007394 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007395 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007396 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007397 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007398
7399 return 0;
7400}
7401
Emeric Brunfb510ea2012-10-05 12:00:26 +02007402/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007403static 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 +02007404{
Emeric Brun051cdab2012-10-02 19:25:50 +02007405#ifndef X509_V_FLAG_CRL_CHECK
7406 if (err)
7407 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7408 return ERR_ALERT | ERR_FATAL;
7409#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007410 if (!*args[cur_arg + 1]) {
7411 if (err)
7412 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7413 return ERR_ALERT | ERR_FATAL;
7414 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007415
Willy Tarreauef934602016-12-22 23:12:01 +01007416 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7417 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007418 else
7419 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007420
Emeric Brun2b58d042012-09-20 17:10:03 +02007421 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007422#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007423}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007424static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7425{
7426 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7427}
Emeric Brun2b58d042012-09-20 17:10:03 +02007428
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007429/* parse the "curves" bind keyword keyword */
7430static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7431{
7432#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7433 if (!*args[cur_arg + 1]) {
7434 if (err)
7435 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7436 return ERR_ALERT | ERR_FATAL;
7437 }
7438 conf->curves = strdup(args[cur_arg + 1]);
7439 return 0;
7440#else
7441 if (err)
7442 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7443 return ERR_ALERT | ERR_FATAL;
7444#endif
7445}
7446static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7447{
7448 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7449}
7450
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007451/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007452static 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 +02007453{
7454#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7455 if (err)
7456 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7457 return ERR_ALERT | ERR_FATAL;
7458#elif defined(OPENSSL_NO_ECDH)
7459 if (err)
7460 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7461 return ERR_ALERT | ERR_FATAL;
7462#else
7463 if (!*args[cur_arg + 1]) {
7464 if (err)
7465 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7466 return ERR_ALERT | ERR_FATAL;
7467 }
7468
7469 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007470
7471 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007472#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007473}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007474static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7475{
7476 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7477}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007478
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007479/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007480static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7481{
7482 int code;
7483 char *p = args[cur_arg + 1];
7484 unsigned long long *ignerr = &conf->crt_ignerr;
7485
7486 if (!*p) {
7487 if (err)
7488 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7489 return ERR_ALERT | ERR_FATAL;
7490 }
7491
7492 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7493 ignerr = &conf->ca_ignerr;
7494
7495 if (strcmp(p, "all") == 0) {
7496 *ignerr = ~0ULL;
7497 return 0;
7498 }
7499
7500 while (p) {
7501 code = atoi(p);
7502 if ((code <= 0) || (code > 63)) {
7503 if (err)
7504 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7505 args[cur_arg], code, args[cur_arg + 1]);
7506 return ERR_ALERT | ERR_FATAL;
7507 }
7508 *ignerr |= 1ULL << code;
7509 p = strchr(p, ',');
7510 if (p)
7511 p++;
7512 }
7513
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007514 return 0;
7515}
7516
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007517/* parse tls_method_options "no-xxx" and "force-xxx" */
7518static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007519{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007520 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007521 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007522 p = strchr(arg, '-');
7523 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007524 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007525 p++;
7526 if (!strcmp(p, "sslv3"))
7527 v = CONF_SSLV3;
7528 else if (!strcmp(p, "tlsv10"))
7529 v = CONF_TLSV10;
7530 else if (!strcmp(p, "tlsv11"))
7531 v = CONF_TLSV11;
7532 else if (!strcmp(p, "tlsv12"))
7533 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007534 else if (!strcmp(p, "tlsv13"))
7535 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007536 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007537 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007538 if (!strncmp(arg, "no-", 3))
7539 methods->flags |= methodVersions[v].flag;
7540 else if (!strncmp(arg, "force-", 6))
7541 methods->min = methods->max = v;
7542 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007543 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007544 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007545 fail:
7546 if (err)
7547 memprintf(err, "'%s' : option not implemented", arg);
7548 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007549}
7550
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007551static 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 +02007552{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007553 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007554}
7555
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007556static 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 +02007557{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007558 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7559}
7560
7561/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7562static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7563{
7564 uint16_t i, v = 0;
7565 char *argv = args[cur_arg + 1];
7566 if (!*argv) {
7567 if (err)
7568 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7569 return ERR_ALERT | ERR_FATAL;
7570 }
7571 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7572 if (!strcmp(argv, methodVersions[i].name))
7573 v = i;
7574 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007575 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007576 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007577 return ERR_ALERT | ERR_FATAL;
7578 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007579 if (!strcmp("ssl-min-ver", args[cur_arg]))
7580 methods->min = v;
7581 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7582 methods->max = v;
7583 else {
7584 if (err)
7585 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7586 return ERR_ALERT | ERR_FATAL;
7587 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007588 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007589}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007590
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007591static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7592{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007593#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007594 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 +02007595#endif
7596 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7597}
7598
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007599static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7600{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007601 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007602}
7603
7604static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7605{
7606 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7607}
7608
Emeric Brun2d0c4822012-10-02 13:45:20 +02007609/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007610static 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 +02007611{
Emeric Brun89675492012-10-05 13:48:26 +02007612 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007613 return 0;
7614}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007615
Olivier Houchardc2aae742017-09-22 18:26:28 +02007616/* parse the "allow-0rtt" bind keyword */
7617static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7618{
7619 conf->early_data = 1;
7620 return 0;
7621}
7622
7623static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7624{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007625 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007626 return 0;
7627}
7628
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007629/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007630static 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 +02007631{
Bernard Spil13c53f82018-02-15 13:34:58 +01007632#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007633 char *p1, *p2;
7634
7635 if (!*args[cur_arg + 1]) {
7636 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7637 return ERR_ALERT | ERR_FATAL;
7638 }
7639
7640 free(conf->npn_str);
7641
Willy Tarreau3724da12016-02-12 17:11:12 +01007642 /* the NPN string is built as a suite of (<len> <name>)*,
7643 * so we reuse each comma to store the next <len> and need
7644 * one more for the end of the string.
7645 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007646 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007647 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007648 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7649
7650 /* replace commas with the name length */
7651 p1 = conf->npn_str;
7652 p2 = p1 + 1;
7653 while (1) {
7654 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7655 if (!p2)
7656 p2 = p1 + 1 + strlen(p1 + 1);
7657
7658 if (p2 - (p1 + 1) > 255) {
7659 *p2 = '\0';
7660 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7661 return ERR_ALERT | ERR_FATAL;
7662 }
7663
7664 *p1 = p2 - (p1 + 1);
7665 p1 = p2;
7666
7667 if (!*p2)
7668 break;
7669
7670 *(p2++) = '\0';
7671 }
7672 return 0;
7673#else
7674 if (err)
7675 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7676 return ERR_ALERT | ERR_FATAL;
7677#endif
7678}
7679
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007680static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7681{
7682 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7683}
7684
Willy Tarreauab861d32013-04-02 02:30:41 +02007685/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007686static 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 +02007687{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007688#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007689 char *p1, *p2;
7690
7691 if (!*args[cur_arg + 1]) {
7692 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7693 return ERR_ALERT | ERR_FATAL;
7694 }
7695
7696 free(conf->alpn_str);
7697
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007698 /* the ALPN string is built as a suite of (<len> <name>)*,
7699 * so we reuse each comma to store the next <len> and need
7700 * one more for the end of the string.
7701 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007702 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007703 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007704 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7705
7706 /* replace commas with the name length */
7707 p1 = conf->alpn_str;
7708 p2 = p1 + 1;
7709 while (1) {
7710 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7711 if (!p2)
7712 p2 = p1 + 1 + strlen(p1 + 1);
7713
7714 if (p2 - (p1 + 1) > 255) {
7715 *p2 = '\0';
7716 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7717 return ERR_ALERT | ERR_FATAL;
7718 }
7719
7720 *p1 = p2 - (p1 + 1);
7721 p1 = p2;
7722
7723 if (!*p2)
7724 break;
7725
7726 *(p2++) = '\0';
7727 }
7728 return 0;
7729#else
7730 if (err)
7731 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7732 return ERR_ALERT | ERR_FATAL;
7733#endif
7734}
7735
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007736static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7737{
7738 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7739}
7740
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007741/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007742static 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 +02007743{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007744 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007745 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007746
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007747 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7748 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007749#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7750 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7751 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7752#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007753 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007754 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7755 if (!conf->ssl_conf.ssl_methods.min)
7756 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7757 if (!conf->ssl_conf.ssl_methods.max)
7758 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007759
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007760 return 0;
7761}
7762
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007763/* parse the "prefer-client-ciphers" bind keyword */
7764static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7765{
7766 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7767 return 0;
7768}
7769
Christopher Faulet31af49d2015-06-09 17:29:50 +02007770/* parse the "generate-certificates" bind keyword */
7771static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7772{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007773#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007774 conf->generate_certs = 1;
7775#else
7776 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7777 err && *err ? *err : "");
7778#endif
7779 return 0;
7780}
7781
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007782/* parse the "strict-sni" bind keyword */
7783static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7784{
7785 conf->strict_sni = 1;
7786 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007787}
7788
7789/* parse the "tls-ticket-keys" bind keyword */
7790static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7791{
7792#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7793 FILE *f;
7794 int i = 0;
7795 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007796 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007797
7798 if (!*args[cur_arg + 1]) {
7799 if (err)
7800 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7801 return ERR_ALERT | ERR_FATAL;
7802 }
7803
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007804 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007805 if (keys_ref) {
7806 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007807 conf->keys_ref = keys_ref;
7808 return 0;
7809 }
7810
Vincent Bernat02779b62016-04-03 13:48:43 +02007811 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007812 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007813
7814 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7815 if (err)
7816 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7817 return ERR_ALERT | ERR_FATAL;
7818 }
7819
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007820 keys_ref->filename = strdup(args[cur_arg + 1]);
7821
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007822 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7823 int len = strlen(thisline);
7824 /* Strip newline characters from the end */
7825 if(thisline[len - 1] == '\n')
7826 thisline[--len] = 0;
7827
7828 if(thisline[len - 1] == '\r')
7829 thisline[--len] = 0;
7830
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007831 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 +01007832 if (err)
7833 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007834 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007835 return ERR_ALERT | ERR_FATAL;
7836 }
7837 i++;
7838 }
7839
7840 if (i < TLS_TICKETS_NO) {
7841 if (err)
7842 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 +02007843 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007844 return ERR_ALERT | ERR_FATAL;
7845 }
7846
7847 fclose(f);
7848
7849 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007850 i -= 2;
7851 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007852 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007853 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007854 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007855 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007856
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007857 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7858
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007859 return 0;
7860#else
7861 if (err)
7862 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7863 return ERR_ALERT | ERR_FATAL;
7864#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007865}
7866
Emeric Brund94b3fe2012-09-20 18:23:56 +02007867/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007868static 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 +02007869{
7870 if (!*args[cur_arg + 1]) {
7871 if (err)
7872 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7873 return ERR_ALERT | ERR_FATAL;
7874 }
7875
7876 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007877 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007878 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007879 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007880 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007881 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007882 else {
7883 if (err)
7884 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7885 args[cur_arg], args[cur_arg + 1]);
7886 return ERR_ALERT | ERR_FATAL;
7887 }
7888
7889 return 0;
7890}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007891static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7892{
7893 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7894}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007895
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007896/* parse the "no-ca-names" bind keyword */
7897static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7898{
7899 conf->no_ca_names = 1;
7900 return 0;
7901}
7902static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7903{
7904 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7905}
7906
Willy Tarreau92faadf2012-10-10 23:04:25 +02007907/************** "server" keywords ****************/
7908
Olivier Houchardc7566002018-11-20 23:33:50 +01007909/* parse the "npn" bind keyword */
7910static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7911{
7912#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7913 char *p1, *p2;
7914
7915 if (!*args[*cur_arg + 1]) {
7916 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7917 return ERR_ALERT | ERR_FATAL;
7918 }
7919
7920 free(newsrv->ssl_ctx.npn_str);
7921
7922 /* the NPN string is built as a suite of (<len> <name>)*,
7923 * so we reuse each comma to store the next <len> and need
7924 * one more for the end of the string.
7925 */
7926 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7927 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7928 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7929 newsrv->ssl_ctx.npn_len);
7930
7931 /* replace commas with the name length */
7932 p1 = newsrv->ssl_ctx.npn_str;
7933 p2 = p1 + 1;
7934 while (1) {
7935 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7936 newsrv->ssl_ctx.npn_len - (p1 + 1));
7937 if (!p2)
7938 p2 = p1 + 1 + strlen(p1 + 1);
7939
7940 if (p2 - (p1 + 1) > 255) {
7941 *p2 = '\0';
7942 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7943 return ERR_ALERT | ERR_FATAL;
7944 }
7945
7946 *p1 = p2 - (p1 + 1);
7947 p1 = p2;
7948
7949 if (!*p2)
7950 break;
7951
7952 *(p2++) = '\0';
7953 }
7954 return 0;
7955#else
7956 if (err)
7957 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7958 return ERR_ALERT | ERR_FATAL;
7959#endif
7960}
7961
7962/* parse the "alpn" bind keyword */
7963static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7964{
7965#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7966 char *p1, *p2;
7967
7968 if (!*args[*cur_arg + 1]) {
7969 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7970 return ERR_ALERT | ERR_FATAL;
7971 }
7972
7973 free(newsrv->ssl_ctx.alpn_str);
7974
7975 /* the ALPN string is built as a suite of (<len> <name>)*,
7976 * so we reuse each comma to store the next <len> and need
7977 * one more for the end of the string.
7978 */
7979 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7980 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7981 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7982 newsrv->ssl_ctx.alpn_len);
7983
7984 /* replace commas with the name length */
7985 p1 = newsrv->ssl_ctx.alpn_str;
7986 p2 = p1 + 1;
7987 while (1) {
7988 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7989 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7990 if (!p2)
7991 p2 = p1 + 1 + strlen(p1 + 1);
7992
7993 if (p2 - (p1 + 1) > 255) {
7994 *p2 = '\0';
7995 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7996 return ERR_ALERT | ERR_FATAL;
7997 }
7998
7999 *p1 = p2 - (p1 + 1);
8000 p1 = p2;
8001
8002 if (!*p2)
8003 break;
8004
8005 *(p2++) = '\0';
8006 }
8007 return 0;
8008#else
8009 if (err)
8010 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8011 return ERR_ALERT | ERR_FATAL;
8012#endif
8013}
8014
Emeric Brunef42d922012-10-11 16:11:36 +02008015/* parse the "ca-file" server keyword */
8016static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8017{
8018 if (!*args[*cur_arg + 1]) {
8019 if (err)
8020 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8021 return ERR_ALERT | ERR_FATAL;
8022 }
8023
Willy Tarreauef934602016-12-22 23:12:01 +01008024 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8025 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008026 else
8027 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8028
8029 return 0;
8030}
8031
Olivier Houchard9130a962017-10-17 17:33:43 +02008032/* parse the "check-sni" server keyword */
8033static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8034{
8035 if (!*args[*cur_arg + 1]) {
8036 if (err)
8037 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8038 return ERR_ALERT | ERR_FATAL;
8039 }
8040
8041 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8042 if (!newsrv->check.sni) {
8043 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8044 return ERR_ALERT | ERR_FATAL;
8045 }
8046 return 0;
8047
8048}
8049
Willy Tarreau92faadf2012-10-10 23:04:25 +02008050/* parse the "check-ssl" server keyword */
8051static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8052{
8053 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008054 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8055 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008056#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8057 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8058 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8059#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008060 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008061 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8062 if (!newsrv->ssl_ctx.methods.min)
8063 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8064 if (!newsrv->ssl_ctx.methods.max)
8065 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8066
Willy Tarreau92faadf2012-10-10 23:04:25 +02008067 return 0;
8068}
8069
8070/* parse the "ciphers" server keyword */
8071static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8072{
8073 if (!*args[*cur_arg + 1]) {
8074 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8075 return ERR_ALERT | ERR_FATAL;
8076 }
8077
8078 free(newsrv->ssl_ctx.ciphers);
8079 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8080 return 0;
8081}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008082
8083#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8084/* parse the "ciphersuites" server keyword */
8085static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8086{
8087 if (!*args[*cur_arg + 1]) {
8088 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8089 return ERR_ALERT | ERR_FATAL;
8090 }
8091
8092 free(newsrv->ssl_ctx.ciphersuites);
8093 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8094 return 0;
8095}
8096#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008097
Emeric Brunef42d922012-10-11 16:11:36 +02008098/* parse the "crl-file" server keyword */
8099static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8100{
8101#ifndef X509_V_FLAG_CRL_CHECK
8102 if (err)
8103 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8104 return ERR_ALERT | ERR_FATAL;
8105#else
8106 if (!*args[*cur_arg + 1]) {
8107 if (err)
8108 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8109 return ERR_ALERT | ERR_FATAL;
8110 }
8111
Willy Tarreauef934602016-12-22 23:12:01 +01008112 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8113 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008114 else
8115 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8116
8117 return 0;
8118#endif
8119}
8120
Emeric Bruna7aa3092012-10-26 12:58:00 +02008121/* parse the "crt" server keyword */
8122static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8123{
8124 if (!*args[*cur_arg + 1]) {
8125 if (err)
8126 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8127 return ERR_ALERT | ERR_FATAL;
8128 }
8129
Willy Tarreauef934602016-12-22 23:12:01 +01008130 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008131 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008132 else
8133 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8134
8135 return 0;
8136}
Emeric Brunef42d922012-10-11 16:11:36 +02008137
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008138/* parse the "no-check-ssl" server keyword */
8139static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8140{
8141 newsrv->check.use_ssl = 0;
8142 free(newsrv->ssl_ctx.ciphers);
8143 newsrv->ssl_ctx.ciphers = NULL;
8144 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8145 return 0;
8146}
8147
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008148/* parse the "no-send-proxy-v2-ssl" server keyword */
8149static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8150{
8151 newsrv->pp_opts &= ~SRV_PP_V2;
8152 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8153 return 0;
8154}
8155
8156/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8157static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8158{
8159 newsrv->pp_opts &= ~SRV_PP_V2;
8160 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8161 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8162 return 0;
8163}
8164
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008165/* parse the "no-ssl" server keyword */
8166static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8167{
8168 newsrv->use_ssl = 0;
8169 free(newsrv->ssl_ctx.ciphers);
8170 newsrv->ssl_ctx.ciphers = NULL;
8171 return 0;
8172}
8173
Olivier Houchard522eea72017-11-03 16:27:47 +01008174/* parse the "allow-0rtt" server keyword */
8175static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8176{
8177 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8178 return 0;
8179}
8180
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008181/* parse the "no-ssl-reuse" server keyword */
8182static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8183{
8184 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8185 return 0;
8186}
8187
Emeric Brunf9c5c472012-10-11 15:28:34 +02008188/* parse the "no-tls-tickets" server keyword */
8189static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8190{
8191 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8192 return 0;
8193}
David Safb76832014-05-08 23:42:08 -04008194/* parse the "send-proxy-v2-ssl" server keyword */
8195static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8196{
8197 newsrv->pp_opts |= SRV_PP_V2;
8198 newsrv->pp_opts |= SRV_PP_V2_SSL;
8199 return 0;
8200}
8201
8202/* parse the "send-proxy-v2-ssl-cn" server keyword */
8203static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8204{
8205 newsrv->pp_opts |= SRV_PP_V2;
8206 newsrv->pp_opts |= SRV_PP_V2_SSL;
8207 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8208 return 0;
8209}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008210
Willy Tarreau732eac42015-07-09 11:40:25 +02008211/* parse the "sni" server keyword */
8212static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8213{
8214#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8215 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8216 return ERR_ALERT | ERR_FATAL;
8217#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008218 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008219
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008220 arg = args[*cur_arg + 1];
8221 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008222 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8223 return ERR_ALERT | ERR_FATAL;
8224 }
8225
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008226 free(newsrv->sni_expr);
8227 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008228
Willy Tarreau732eac42015-07-09 11:40:25 +02008229 return 0;
8230#endif
8231}
8232
Willy Tarreau92faadf2012-10-10 23:04:25 +02008233/* parse the "ssl" server keyword */
8234static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8235{
8236 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008237 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8238 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008239#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8240 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8241 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8242#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008243 return 0;
8244}
8245
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008246/* parse the "ssl-reuse" server keyword */
8247static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8248{
8249 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8250 return 0;
8251}
8252
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008253/* parse the "tls-tickets" server keyword */
8254static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8255{
8256 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8257 return 0;
8258}
8259
Emeric Brunef42d922012-10-11 16:11:36 +02008260/* parse the "verify" server keyword */
8261static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8262{
8263 if (!*args[*cur_arg + 1]) {
8264 if (err)
8265 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8266 return ERR_ALERT | ERR_FATAL;
8267 }
8268
8269 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008270 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008271 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008272 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008273 else {
8274 if (err)
8275 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8276 args[*cur_arg], args[*cur_arg + 1]);
8277 return ERR_ALERT | ERR_FATAL;
8278 }
8279
Evan Broderbe554312013-06-27 00:05:25 -07008280 return 0;
8281}
8282
8283/* parse the "verifyhost" server keyword */
8284static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8285{
8286 if (!*args[*cur_arg + 1]) {
8287 if (err)
8288 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8289 return ERR_ALERT | ERR_FATAL;
8290 }
8291
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008292 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008293 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8294
Emeric Brunef42d922012-10-11 16:11:36 +02008295 return 0;
8296}
8297
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008298/* parse the "ssl-default-bind-options" keyword in global section */
8299static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8300 struct proxy *defpx, const char *file, int line,
8301 char **err) {
8302 int i = 1;
8303
8304 if (*(args[i]) == 0) {
8305 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8306 return -1;
8307 }
8308 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008309 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008310 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008311 else if (!strcmp(args[i], "prefer-client-ciphers"))
8312 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008313 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8314 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8315 i++;
8316 else {
8317 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8318 return -1;
8319 }
8320 }
8321 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008322 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8323 return -1;
8324 }
8325 i++;
8326 }
8327 return 0;
8328}
8329
8330/* parse the "ssl-default-server-options" keyword in global section */
8331static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8332 struct proxy *defpx, const char *file, int line,
8333 char **err) {
8334 int i = 1;
8335
8336 if (*(args[i]) == 0) {
8337 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8338 return -1;
8339 }
8340 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008341 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008342 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008343 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8344 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8345 i++;
8346 else {
8347 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8348 return -1;
8349 }
8350 }
8351 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008352 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8353 return -1;
8354 }
8355 i++;
8356 }
8357 return 0;
8358}
8359
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008360/* parse the "ca-base" / "crt-base" keywords in global section.
8361 * Returns <0 on alert, >0 on warning, 0 on success.
8362 */
8363static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8364 struct proxy *defpx, const char *file, int line,
8365 char **err)
8366{
8367 char **target;
8368
Willy Tarreauef934602016-12-22 23:12:01 +01008369 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008370
8371 if (too_many_args(1, args, err, NULL))
8372 return -1;
8373
8374 if (*target) {
8375 memprintf(err, "'%s' already specified.", args[0]);
8376 return -1;
8377 }
8378
8379 if (*(args[1]) == 0) {
8380 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8381 return -1;
8382 }
8383 *target = strdup(args[1]);
8384 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008385}
8386
8387/* parse the "ssl-mode-async" keyword in global section.
8388 * Returns <0 on alert, >0 on warning, 0 on success.
8389 */
8390static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8391 struct proxy *defpx, const char *file, int line,
8392 char **err)
8393{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008394#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008395 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008396 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008397 return 0;
8398#else
8399 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8400 return -1;
8401#endif
8402}
8403
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008404#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008405static int ssl_check_async_engine_count(void) {
8406 int err_code = 0;
8407
Emeric Brun3854e012017-05-17 20:42:48 +02008408 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008409 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008410 err_code = ERR_ABORT;
8411 }
8412 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008413}
8414
Grant Zhang872f9c22017-01-21 01:10:18 +00008415/* parse the "ssl-engine" keyword in global section.
8416 * Returns <0 on alert, >0 on warning, 0 on success.
8417 */
8418static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8419 struct proxy *defpx, const char *file, int line,
8420 char **err)
8421{
8422 char *algo;
8423 int ret = -1;
8424
8425 if (*(args[1]) == 0) {
8426 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8427 return ret;
8428 }
8429
8430 if (*(args[2]) == 0) {
8431 /* if no list of algorithms is given, it defaults to ALL */
8432 algo = strdup("ALL");
8433 goto add_engine;
8434 }
8435
8436 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8437 if (strcmp(args[2], "algo") != 0) {
8438 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8439 return ret;
8440 }
8441
8442 if (*(args[3]) == 0) {
8443 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8444 return ret;
8445 }
8446 algo = strdup(args[3]);
8447
8448add_engine:
8449 if (ssl_init_single_engine(args[1], algo)==0) {
8450 openssl_engines_initialized++;
8451 ret = 0;
8452 }
8453 free(algo);
8454 return ret;
8455}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008456#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008457
Willy Tarreauf22e9682016-12-21 23:23:19 +01008458/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8459 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8460 */
8461static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8462 struct proxy *defpx, const char *file, int line,
8463 char **err)
8464{
8465 char **target;
8466
Willy Tarreauef934602016-12-22 23:12:01 +01008467 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008468
8469 if (too_many_args(1, args, err, NULL))
8470 return -1;
8471
8472 if (*(args[1]) == 0) {
8473 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8474 return -1;
8475 }
8476
8477 free(*target);
8478 *target = strdup(args[1]);
8479 return 0;
8480}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008481
8482#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8483/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8484 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8485 */
8486static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8487 struct proxy *defpx, const char *file, int line,
8488 char **err)
8489{
8490 char **target;
8491
8492 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8493
8494 if (too_many_args(1, args, err, NULL))
8495 return -1;
8496
8497 if (*(args[1]) == 0) {
8498 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8499 return -1;
8500 }
8501
8502 free(*target);
8503 *target = strdup(args[1]);
8504 return 0;
8505}
8506#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008507
Willy Tarreau9ceda382016-12-21 23:13:03 +01008508/* parse various global tune.ssl settings consisting in positive integers.
8509 * Returns <0 on alert, >0 on warning, 0 on success.
8510 */
8511static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8512 struct proxy *defpx, const char *file, int line,
8513 char **err)
8514{
8515 int *target;
8516
8517 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8518 target = &global.tune.sslcachesize;
8519 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008520 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008521 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008522 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008523 else if (strcmp(args[0], "maxsslconn") == 0)
8524 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008525 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8526 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008527 else {
8528 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8529 return -1;
8530 }
8531
8532 if (too_many_args(1, args, err, NULL))
8533 return -1;
8534
8535 if (*(args[1]) == 0) {
8536 memprintf(err, "'%s' expects an integer argument.", args[0]);
8537 return -1;
8538 }
8539
8540 *target = atoi(args[1]);
8541 if (*target < 0) {
8542 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8543 return -1;
8544 }
8545 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008546}
8547
8548static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8549 struct proxy *defpx, const char *file, int line,
8550 char **err)
8551{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008552 int ret;
8553
8554 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8555 if (ret != 0)
8556 return ret;
8557
Willy Tarreaubafbe012017-11-24 17:34:44 +01008558 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008559 memprintf(err, "'%s' is already configured.", args[0]);
8560 return -1;
8561 }
8562
Willy Tarreaubafbe012017-11-24 17:34:44 +01008563 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8564 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008565 memprintf(err, "Out of memory error.");
8566 return -1;
8567 }
8568 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008569}
8570
8571/* parse "ssl.force-private-cache".
8572 * Returns <0 on alert, >0 on warning, 0 on success.
8573 */
8574static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8575 struct proxy *defpx, const char *file, int line,
8576 char **err)
8577{
8578 if (too_many_args(0, args, err, NULL))
8579 return -1;
8580
Willy Tarreauef934602016-12-22 23:12:01 +01008581 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008582 return 0;
8583}
8584
8585/* parse "ssl.lifetime".
8586 * Returns <0 on alert, >0 on warning, 0 on success.
8587 */
8588static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8589 struct proxy *defpx, const char *file, int line,
8590 char **err)
8591{
8592 const char *res;
8593
8594 if (too_many_args(1, args, err, NULL))
8595 return -1;
8596
8597 if (*(args[1]) == 0) {
8598 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8599 return -1;
8600 }
8601
Willy Tarreauef934602016-12-22 23:12:01 +01008602 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008603 if (res) {
8604 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8605 return -1;
8606 }
8607 return 0;
8608}
8609
8610#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008611/* parse "ssl-dh-param-file".
8612 * Returns <0 on alert, >0 on warning, 0 on success.
8613 */
8614static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8615 struct proxy *defpx, const char *file, int line,
8616 char **err)
8617{
8618 if (too_many_args(1, args, err, NULL))
8619 return -1;
8620
8621 if (*(args[1]) == 0) {
8622 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8623 return -1;
8624 }
8625
8626 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8627 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8628 return -1;
8629 }
8630 return 0;
8631}
8632
Willy Tarreau9ceda382016-12-21 23:13:03 +01008633/* parse "ssl.default-dh-param".
8634 * Returns <0 on alert, >0 on warning, 0 on success.
8635 */
8636static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8637 struct proxy *defpx, const char *file, int line,
8638 char **err)
8639{
8640 if (too_many_args(1, args, err, NULL))
8641 return -1;
8642
8643 if (*(args[1]) == 0) {
8644 memprintf(err, "'%s' expects an integer argument.", args[0]);
8645 return -1;
8646 }
8647
Willy Tarreauef934602016-12-22 23:12:01 +01008648 global_ssl.default_dh_param = atoi(args[1]);
8649 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008650 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8651 return -1;
8652 }
8653 return 0;
8654}
8655#endif
8656
8657
William Lallemand32af2032016-10-29 18:09:35 +02008658/* This function is used with TLS ticket keys management. It permits to browse
8659 * each reference. The variable <getnext> must contain the current node,
8660 * <end> point to the root node.
8661 */
8662#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8663static inline
8664struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8665{
8666 struct tls_keys_ref *ref = getnext;
8667
8668 while (1) {
8669
8670 /* Get next list entry. */
8671 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8672
8673 /* If the entry is the last of the list, return NULL. */
8674 if (&ref->list == end)
8675 return NULL;
8676
8677 return ref;
8678 }
8679}
8680
8681static inline
8682struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8683{
8684 int id;
8685 char *error;
8686
8687 /* If the reference starts by a '#', this is numeric id. */
8688 if (reference[0] == '#') {
8689 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8690 id = strtol(reference + 1, &error, 10);
8691 if (*error != '\0')
8692 return NULL;
8693
8694 /* Perform the unique id lookup. */
8695 return tlskeys_ref_lookupid(id);
8696 }
8697
8698 /* Perform the string lookup. */
8699 return tlskeys_ref_lookup(reference);
8700}
8701#endif
8702
8703
8704#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8705
8706static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8707
8708static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8709 return cli_io_handler_tlskeys_files(appctx);
8710}
8711
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008712/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8713 * (next index to be dumped), and cli.p0 (next key reference).
8714 */
William Lallemand32af2032016-10-29 18:09:35 +02008715static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8716
8717 struct stream_interface *si = appctx->owner;
8718
8719 switch (appctx->st2) {
8720 case STAT_ST_INIT:
8721 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008722 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008723 * later and restart at the state "STAT_ST_INIT".
8724 */
8725 chunk_reset(&trash);
8726
8727 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8728 chunk_appendf(&trash, "# id secret\n");
8729 else
8730 chunk_appendf(&trash, "# id (file)\n");
8731
Willy Tarreau06d80a92017-10-19 14:32:15 +02008732 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008733 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008734 return 0;
8735 }
8736
William Lallemand32af2032016-10-29 18:09:35 +02008737 /* Now, we start the browsing of the references lists.
8738 * Note that the following call to LIST_ELEM return bad pointer. The only
8739 * available field of this pointer is <list>. It is used with the function
8740 * tlskeys_list_get_next() for retruning the first available entry
8741 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008742 if (appctx->ctx.cli.p0 == NULL) {
8743 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8744 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008745 }
8746
8747 appctx->st2 = STAT_ST_LIST;
8748 /* fall through */
8749
8750 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008751 while (appctx->ctx.cli.p0) {
8752 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008753
8754 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008755 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008756 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008757
8758 if (appctx->ctx.cli.i1 == 0)
8759 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8760
William Lallemand32af2032016-10-29 18:09:35 +02008761 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008762 int head;
8763
8764 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8765 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008766 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008767 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008768
8769 chunk_reset(t2);
8770 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008771 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8772 sizeof(struct tls_sess_key),
8773 t2->area, t2->size);
8774 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8775 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008776
Willy Tarreau06d80a92017-10-19 14:32:15 +02008777 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008778 /* let's try again later from this stream. We add ourselves into
8779 * this stream's users so that it can remove us upon termination.
8780 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008781 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008782 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008783 return 0;
8784 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008785 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008786 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008787 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008788 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008789 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008790 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008791 /* let's try again later from this stream. We add ourselves into
8792 * this stream's users so that it can remove us upon termination.
8793 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008794 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008795 return 0;
8796 }
8797
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008798 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008799 break;
8800
8801 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008802 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008803 }
8804
8805 appctx->st2 = STAT_ST_FIN;
8806 /* fall through */
8807
8808 default:
8809 appctx->st2 = STAT_ST_FIN;
8810 return 1;
8811 }
8812 return 0;
8813}
8814
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008815/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008816static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008817{
William Lallemand32af2032016-10-29 18:09:35 +02008818 /* no parameter, shows only file list */
8819 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008820 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008821 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008822 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008823 }
8824
8825 if (args[2][0] == '*') {
8826 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008827 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008828 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008829 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8830 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008831 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008832 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008833 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008834 return 1;
8835 }
8836 }
William Lallemand32af2032016-10-29 18:09:35 +02008837 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008838 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008839}
8840
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008841static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008842{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008843 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008844 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008845
William Lallemand32af2032016-10-29 18:09:35 +02008846 /* Expect two parameters: the filename and the new new TLS key in encoding */
8847 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008848 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008849 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 +01008850 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008851 return 1;
8852 }
8853
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008854 ref = tlskeys_ref_lookup_ref(args[3]);
8855 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008856 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008857 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008858 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008859 return 1;
8860 }
8861
Willy Tarreau1c913e42018-08-22 05:26:57 +02008862 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8863 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008864 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008865 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008866 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008867 return 1;
8868 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008869 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008870 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008871 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008872 appctx->ctx.cli.msg = "TLS ticket key updated!\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
8876}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008877#endif
William Lallemand32af2032016-10-29 18:09:35 +02008878
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008879static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008880{
8881#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8882 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008883 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008884
8885 if (!payload)
8886 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008887
8888 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008889 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008890 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008891 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008892 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008893 return 1;
8894 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008895
8896 /* remove \r and \n from the payload */
8897 for (i = 0, j = 0; payload[i]; i++) {
8898 if (payload[i] == '\r' || payload[i] == '\n')
8899 continue;
8900 payload[j++] = payload[i];
8901 }
8902 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008903
Willy Tarreau1c913e42018-08-22 05:26:57 +02008904 ret = base64dec(payload, j, trash.area, trash.size);
8905 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008906 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008907 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008908 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008909 return 1;
8910 }
8911
Willy Tarreau1c913e42018-08-22 05:26:57 +02008912 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008913 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8914 if (err) {
8915 memprintf(&err, "%s.\n", err);
8916 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008917 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008918 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008919 else {
8920 appctx->ctx.cli.severity = LOG_ERR;
8921 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8922 appctx->st0 = CLI_ST_PRINT;
8923 }
William Lallemand32af2032016-10-29 18:09:35 +02008924 return 1;
8925 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008926 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008927 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008928 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008929 return 1;
8930#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008931 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008932 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 +01008933 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008934 return 1;
8935#endif
8936
8937}
8938
8939/* register cli keywords */
8940static struct cli_kw_list cli_kws = {{ },{
8941#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8942 { { "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 +02008943 { { "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 +02008944#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008945 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008946 { { NULL }, NULL, NULL, NULL }
8947}};
8948
Willy Tarreau0108d902018-11-25 19:14:37 +01008949INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008950
Willy Tarreau7875d092012-09-10 08:20:03 +02008951/* Note: must not be declared <const> as its list will be overwritten.
8952 * Please take care of keeping this list alphabetically sorted.
8953 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008954static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008955 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008956 { "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 +01008957#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01008958 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008959#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008960 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008961#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8962 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8963#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008964 { "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 +02008965 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008966 { "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 +02008967 { "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 -04008968#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008969 { "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 -04008970#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008971#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8972 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8973#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008974 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8975 { "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 +01008976 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008977 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008978 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8979 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8980 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8981 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8982 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8983 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8984 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8985 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008986 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008987 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8988 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008989 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008990 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8991 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8992 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8993 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8994 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8995 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8996 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008997 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008998 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008999 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009000 { "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 +01009001 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009002 { "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 +02009003 { "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 +01009004 { "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 +02009005 { "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 +01009006#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009007 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009008#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009009#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009010 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009011#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009012 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009013#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009014 { "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 -04009015#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009016 { "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 -04009017#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009018 { "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 -04009019#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009020#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9021 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9022#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009023#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009024 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009025#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009026 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9027 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9028 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9029 { "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 +02009030 { NULL, NULL, 0, 0, 0 },
9031}};
9032
Willy Tarreau0108d902018-11-25 19:14:37 +01009033INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9034
Willy Tarreau7875d092012-09-10 08:20:03 +02009035/* Note: must not be declared <const> as its list will be overwritten.
9036 * Please take care of keeping this list alphabetically sorted.
9037 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009038static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009039 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9040 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009041 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009042}};
9043
Willy Tarreau0108d902018-11-25 19:14:37 +01009044INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9045
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009046/* Note: must not be declared <const> as its list will be overwritten.
9047 * Please take care of keeping this list alphabetically sorted, doing so helps
9048 * all code contributors.
9049 * Optional keywords are also declared with a NULL ->parse() function so that
9050 * the config parser can report an appropriate error when a known keyword was
9051 * not enabled.
9052 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009053static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009054 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009055 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9056 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9057 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009058#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9059 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9060#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009061 { "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 +01009062 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009063 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009064 { "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 +01009065 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009066 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9067 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009068 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9069 { NULL, NULL, 0 },
9070};
9071
Willy Tarreau0108d902018-11-25 19:14:37 +01009072/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9073
Willy Tarreau51fb7652012-09-18 18:24:39 +02009074static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009075 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009076 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9077 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9078 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9079 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9080 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9081 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009082#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9083 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9084#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009085 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9086 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9087 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9088 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9089 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9090 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9091 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9092 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9093 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9094 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009095 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009096 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009097 { "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 +02009098 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9099 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9100 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9101 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009102 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009103 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9104 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009105 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9106 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009107 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9108 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9109 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9110 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9111 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009112 { NULL, NULL, 0 },
9113}};
Emeric Brun46591952012-05-18 15:47:34 +02009114
Willy Tarreau0108d902018-11-25 19:14:37 +01009115INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9116
Willy Tarreau92faadf2012-10-10 23:04:25 +02009117/* Note: must not be declared <const> as its list will be overwritten.
9118 * Please take care of keeping this list alphabetically sorted, doing so helps
9119 * all code contributors.
9120 * Optional keywords are also declared with a NULL ->parse() function so that
9121 * the config parser can report an appropriate error when a known keyword was
9122 * not enabled.
9123 */
9124static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009125 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009126 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009127 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009128 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009129 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9130 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009131#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9132 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9133#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009134 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9135 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9136 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9137 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9138 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9139 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9140 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9141 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9142 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9143 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9144 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9145 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9146 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9147 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9148 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9149 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9150 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9151 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009152 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009153 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9154 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9155 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9156 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9157 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9158 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9159 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9160 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9161 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9162 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009163 { NULL, NULL, 0, 0 },
9164}};
9165
Willy Tarreau0108d902018-11-25 19:14:37 +01009166INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9167
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009168static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009169 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9170 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009171 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009172 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9173 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009174#ifndef OPENSSL_NO_DH
9175 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9176#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009177 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009178#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009179 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009180#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009181 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9182#ifndef OPENSSL_NO_DH
9183 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9184#endif
9185 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9186 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9187 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9188 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009189 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009190 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9191 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009192#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9193 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9194 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9195#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009196 { 0, NULL, NULL },
9197}};
9198
Willy Tarreau0108d902018-11-25 19:14:37 +01009199INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9200
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009201/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009202static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009203 .snd_buf = ssl_sock_from_buf,
9204 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009205 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009206 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009207 .rcv_pipe = NULL,
9208 .snd_pipe = NULL,
9209 .shutr = NULL,
9210 .shutw = ssl_sock_shutw,
9211 .close = ssl_sock_close,
9212 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009213 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009214 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009215 .prepare_srv = ssl_sock_prepare_srv_ctx,
9216 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009217 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009218 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009219};
9220
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009221enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9222 struct session *sess, struct stream *s, int flags)
9223{
9224 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009225 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009226
9227 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009228 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009229
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009230 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009231 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009232 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009233 s->req.flags |= CF_READ_NULL;
9234 return ACT_RET_YIELD;
9235 }
9236 }
9237 return (ACT_RET_CONT);
9238}
9239
9240static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9241{
9242 rule->action_ptr = ssl_action_wait_for_hs;
9243
9244 return ACT_RET_PRS_OK;
9245}
9246
9247static struct action_kw_list http_req_actions = {ILH, {
9248 { "wait-for-handshake", ssl_parse_wait_for_hs },
9249 { /* END */ }
9250}};
9251
Willy Tarreau0108d902018-11-25 19:14:37 +01009252INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9253
Daniel Jakots54ffb912015-11-06 20:02:41 +01009254#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009255
9256static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9257{
9258 if (ptr) {
9259 chunk_destroy(ptr);
9260 free(ptr);
9261 }
9262}
9263
9264#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009265static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9266{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009267 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009268}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009269
Emeric Brun46591952012-05-18 15:47:34 +02009270__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009271static void __ssl_sock_init(void)
9272{
Emeric Brun46591952012-05-18 15:47:34 +02009273 STACK_OF(SSL_COMP)* cm;
9274
Willy Tarreauef934602016-12-22 23:12:01 +01009275 if (global_ssl.listen_default_ciphers)
9276 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9277 if (global_ssl.connect_default_ciphers)
9278 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009279#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9280 if (global_ssl.listen_default_ciphersuites)
9281 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9282 if (global_ssl.connect_default_ciphersuites)
9283 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9284#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009285
Willy Tarreau13e14102016-12-22 20:25:26 +01009286 xprt_register(XPRT_SSL, &ssl_sock);
Rosen Penev68185952018-12-14 08:47:02 -08009287#if OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +02009288 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -08009289#endif
Emeric Brun46591952012-05-18 15:47:34 +02009290 cm = SSL_COMP_get_compression_methods();
9291 sk_SSL_COMP_zero(cm);
Rosen Penev68185952018-12-14 08:47:02 -08009292#if defined(USE_THREAD) && ((OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER))
Emeric Brun821bb9b2017-06-15 16:37:39 +02009293 ssl_locking_init();
9294#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009295#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009296 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9297#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009298 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009299 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 +01009300 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009301#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009302 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009303 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009304#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009305#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9306 hap_register_post_check(tlskeys_finalize_config);
9307#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009308
9309 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9310 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9311
9312#ifndef OPENSSL_NO_DH
9313 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9314 hap_register_post_deinit(ssl_free_dh);
9315#endif
9316#ifndef OPENSSL_NO_ENGINE
9317 hap_register_post_deinit(ssl_free_engines);
9318#endif
9319 /* Load SSL string for the verbose & debug mode. */
9320 ERR_load_SSL_strings();
9321}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009322
Willy Tarreau80713382018-11-26 10:19:54 +01009323/* Compute and register the version string */
9324static void ssl_register_build_options()
9325{
9326 char *ptr = NULL;
9327 int i;
9328
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009329 memprintf(&ptr, "Built with OpenSSL version : "
9330#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009331 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009332#else /* OPENSSL_IS_BORINGSSL */
9333 OPENSSL_VERSION_TEXT
9334 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -08009335 OpenSSL_version(OPENSSL_VERSION),
9336 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009337#endif
9338 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9339#if OPENSSL_VERSION_NUMBER < 0x00907000L
9340 "no (library version too old)"
9341#elif defined(OPENSSL_NO_TLSEXT)
9342 "no (disabled via OPENSSL_NO_TLSEXT)"
9343#else
9344 "yes"
9345#endif
9346 "", ptr);
9347
9348 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9349#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9350 "yes"
9351#else
9352#ifdef OPENSSL_NO_TLSEXT
9353 "no (because of OPENSSL_NO_TLSEXT)"
9354#else
9355 "no (version might be too old, 0.9.8f min needed)"
9356#endif
9357#endif
9358 "", ptr);
9359
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009360 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9361 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9362 if (methodVersions[i].option)
9363 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009364
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009365 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009366}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009367
Willy Tarreau80713382018-11-26 10:19:54 +01009368INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009369
Emeric Brun46591952012-05-18 15:47:34 +02009370
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009371#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009372void ssl_free_engines(void) {
9373 struct ssl_engine_list *wl, *wlb;
9374 /* free up engine list */
9375 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9376 ENGINE_finish(wl->e);
9377 ENGINE_free(wl->e);
9378 LIST_DEL(&wl->list);
9379 free(wl);
9380 }
9381}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009382#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009383
Remi Gacogned3a23c32015-05-28 16:39:47 +02009384#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009385void ssl_free_dh(void) {
9386 if (local_dh_1024) {
9387 DH_free(local_dh_1024);
9388 local_dh_1024 = NULL;
9389 }
9390 if (local_dh_2048) {
9391 DH_free(local_dh_2048);
9392 local_dh_2048 = NULL;
9393 }
9394 if (local_dh_4096) {
9395 DH_free(local_dh_4096);
9396 local_dh_4096 = NULL;
9397 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009398 if (global_dh) {
9399 DH_free(global_dh);
9400 global_dh = NULL;
9401 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009402}
9403#endif
9404
9405__attribute__((destructor))
9406static void __ssl_sock_deinit(void)
9407{
9408#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009409 if (ssl_ctx_lru_tree) {
9410 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009411 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009412 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009413#endif
9414
Rosen Penev68185952018-12-14 08:47:02 -08009415#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009416 ERR_remove_state(0);
9417 ERR_free_strings();
9418
9419 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -08009420#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +02009421
Rosen Penev68185952018-12-14 08:47:02 -08009422#if ((OPENSSL_VERSION_NUMBER >= 0x00907000L) && (OPENSSL_VERSION_NUMBER < 0x10100000L)) || defined(LIBRESSL_VERSION_NUMBER)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009423 CRYPTO_cleanup_all_ex_data();
9424#endif
9425}
9426
9427
Emeric Brun46591952012-05-18 15:47:34 +02009428/*
9429 * Local variables:
9430 * c-indent-level: 8
9431 * c-basic-offset: 8
9432 * End:
9433 */