blob: 13ce2e5bb8c4bd422c8dc890a65c081671bb7470 [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)
Olivier Houchard51088ce2019-01-02 18:46:41 +01003872 if (bind_conf->ssl_conf.early_data) {
3873 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
3874 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
3875 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003876 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3877 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003878#else
3879 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003880#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003881 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003882#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003883 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003884}
3885
William Lallemand4f45bb92017-10-30 20:08:51 +01003886
3887static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3888{
3889 if (first == block) {
3890 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3891 if (first->len > 0)
3892 sh_ssl_sess_tree_delete(sh_ssl_sess);
3893 }
3894}
3895
3896/* return first block from sh_ssl_sess */
3897static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3898{
3899 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3900
3901}
3902
3903/* store a session into the cache
3904 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3905 * data: asn1 encoded session
3906 * data_len: asn1 encoded session length
3907 * Returns 1 id session was stored (else 0)
3908 */
3909static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3910{
3911 struct shared_block *first;
3912 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3913
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003914 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003915 if (!first) {
3916 /* Could not retrieve enough free blocks to store that session */
3917 return 0;
3918 }
3919
3920 /* STORE the key in the first elem */
3921 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3922 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3923 first->len = sizeof(struct sh_ssl_sess_hdr);
3924
3925 /* it returns the already existing node
3926 or current node if none, never returns null */
3927 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3928 if (oldsh_ssl_sess != sh_ssl_sess) {
3929 /* NOTE: Row couldn't be in use because we lock read & write function */
3930 /* release the reserved row */
3931 shctx_row_dec_hot(ssl_shctx, first);
3932 /* replace the previous session already in the tree */
3933 sh_ssl_sess = oldsh_ssl_sess;
3934 /* ignore the previous session data, only use the header */
3935 first = sh_ssl_sess_first_block(sh_ssl_sess);
3936 shctx_row_inc_hot(ssl_shctx, first);
3937 first->len = sizeof(struct sh_ssl_sess_hdr);
3938 }
3939
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003940 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003941 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003942 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003943 }
3944
3945 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003946
3947 return 1;
3948}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003949
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003950/* SSL callback used when a new session is created while connecting to a server */
3951static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3952{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003953 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003954 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003955
Willy Tarreau07d94e42018-09-20 10:57:52 +02003956 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003957
Olivier Houcharde6060c52017-11-16 17:42:52 +01003958 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3959 int len;
3960 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003961
Olivier Houcharde6060c52017-11-16 17:42:52 +01003962 len = i2d_SSL_SESSION(sess, NULL);
3963 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3964 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3965 } else {
3966 free(s->ssl_ctx.reused_sess[tid].ptr);
3967 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3968 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3969 }
3970 if (s->ssl_ctx.reused_sess[tid].ptr) {
3971 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3972 &ptr);
3973 }
3974 } else {
3975 free(s->ssl_ctx.reused_sess[tid].ptr);
3976 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3977 }
3978
3979 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003980}
3981
Olivier Houcharde6060c52017-11-16 17:42:52 +01003982
William Lallemanded0b5ad2017-10-30 19:36:36 +01003983/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003984int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003985{
3986 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3987 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3988 unsigned char *p;
3989 int data_len;
3990 unsigned int sid_length, sid_ctx_length;
3991 const unsigned char *sid_data;
3992 const unsigned char *sid_ctx_data;
3993
3994 /* Session id is already stored in to key and session id is known
3995 * so we dont store it to keep size.
3996 */
3997
3998 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3999 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4000 SSL_SESSION_set1_id(sess, sid_data, 0);
4001 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4002
4003 /* check if buffer is large enough for the ASN1 encoded session */
4004 data_len = i2d_SSL_SESSION(sess, NULL);
4005 if (data_len > SHSESS_MAX_DATA_LEN)
4006 goto err;
4007
4008 p = encsess;
4009
4010 /* process ASN1 session encoding before the lock */
4011 i2d_SSL_SESSION(sess, &p);
4012
4013 memcpy(encid, sid_data, sid_length);
4014 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4015 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4016
William Lallemanda3c77cf2017-10-30 23:44:40 +01004017 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004018 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004019 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004020 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004021err:
4022 /* reset original length values */
4023 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4024 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4025
4026 return 0; /* do not increment session reference count */
4027}
4028
4029/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004030SSL_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 +01004031{
William Lallemand4f45bb92017-10-30 20:08:51 +01004032 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004033 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4034 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004035 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004036 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004037
4038 global.shctx_lookups++;
4039
4040 /* allow the session to be freed automatically by openssl */
4041 *do_copy = 0;
4042
4043 /* tree key is zeros padded sessionid */
4044 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4045 memcpy(tmpkey, key, key_len);
4046 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4047 key = tmpkey;
4048 }
4049
4050 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004051 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004052
4053 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004054 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4055 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004057 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004058 global.shctx_misses++;
4059 return NULL;
4060 }
4061
William Lallemand4f45bb92017-10-30 20:08:51 +01004062 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4063 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004064
William Lallemand4f45bb92017-10-30 20:08:51 +01004065 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 +01004066
William Lallemanda3c77cf2017-10-30 23:44:40 +01004067 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004068
4069 /* decode ASN1 session */
4070 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004071 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004072 /* Reset session id and session id contenxt */
4073 if (sess) {
4074 SSL_SESSION_set1_id(sess, key, key_len);
4075 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4076 }
4077
4078 return sess;
4079}
4080
William Lallemand4f45bb92017-10-30 20:08:51 +01004081
William Lallemanded0b5ad2017-10-30 19:36:36 +01004082/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004083void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004084{
William Lallemand4f45bb92017-10-30 20:08:51 +01004085 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004086 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4087 unsigned int sid_length;
4088 const unsigned char *sid_data;
4089 (void)ctx;
4090
4091 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4092 /* tree key is zeros padded sessionid */
4093 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4094 memcpy(tmpkey, sid_data, sid_length);
4095 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4096 sid_data = tmpkey;
4097 }
4098
William Lallemanda3c77cf2017-10-30 23:44:40 +01004099 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004100
4101 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004102 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4103 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004104 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004105 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004106 }
4107
4108 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004109 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004110}
4111
4112/* Set session cache mode to server and disable openssl internal cache.
4113 * Set shared cache callbacks on an ssl context.
4114 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004115void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004116{
4117 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4118
4119 if (!ssl_shctx) {
4120 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4121 return;
4122 }
4123
4124 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4125 SSL_SESS_CACHE_NO_INTERNAL |
4126 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4127
4128 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004129 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4130 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4131 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004132}
4133
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004134int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4135{
4136 struct proxy *curproxy = bind_conf->frontend;
4137 int cfgerr = 0;
4138 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004139 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004140 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004141#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4142 const char *conf_ciphersuites;
4143#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004144 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004145
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004146 if (ssl_conf) {
4147 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4148 int i, min, max;
4149 int flags = MC_SSL_O_ALL;
4150
4151 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004152 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4153 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004154 if (min)
4155 flags |= (methodVersions[min].flag - 1);
4156 if (max)
4157 flags |= ~((methodVersions[max].flag << 1) - 1);
4158 min = max = CONF_TLSV_NONE;
4159 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4160 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4161 if (min)
4162 max = i;
4163 else
4164 min = max = i;
4165 }
4166 /* save real min/max */
4167 conf_ssl_methods->min = min;
4168 conf_ssl_methods->max = max;
4169 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004170 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4171 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004172 cfgerr += 1;
4173 }
4174 }
4175
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004176 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004177 case SSL_SOCK_VERIFY_NONE:
4178 verify = SSL_VERIFY_NONE;
4179 break;
4180 case SSL_SOCK_VERIFY_OPTIONAL:
4181 verify = SSL_VERIFY_PEER;
4182 break;
4183 case SSL_SOCK_VERIFY_REQUIRED:
4184 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4185 break;
4186 }
4187 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4188 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004189 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4190 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4191 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004192 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004193 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004194 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4195 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004196 cfgerr++;
4197 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004198 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4199 /* set CA names for client cert request, function returns void */
4200 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4201 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004202 }
Emeric Brun850efd52014-01-29 12:24:34 +01004203 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004204 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4205 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004206 cfgerr++;
4207 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004208#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004209 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004210 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4211
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004212 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004213 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4214 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004215 cfgerr++;
4216 }
Emeric Brun561e5742012-10-02 15:20:55 +02004217 else {
4218 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4219 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004220 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004221#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004222 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004223 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004224#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004225 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004226 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004227 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4228 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004229 cfgerr++;
4230 }
4231 }
4232#endif
4233
William Lallemand4f45bb92017-10-30 20:08:51 +01004234 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004235 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4236 if (conf_ciphers &&
4237 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004238 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4239 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004240 cfgerr++;
4241 }
4242
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004243#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4244 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4245 if (conf_ciphersuites &&
4246 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4247 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4248 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4249 cfgerr++;
4250 }
4251#endif
4252
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004253#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004254 /* If tune.ssl.default-dh-param has not been set,
4255 neither has ssl-default-dh-file and no static DH
4256 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004257 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004258 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004259 (ssl_dh_ptr_index == -1 ||
4260 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004261 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4262 const SSL_CIPHER * cipher = NULL;
4263 char cipher_description[128];
4264 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4265 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4266 which is not ephemeral DH. */
4267 const char dhe_description[] = " Kx=DH ";
4268 const char dhe_export_description[] = " Kx=DH(";
4269 int idx = 0;
4270 int dhe_found = 0;
4271 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004272
Remi Gacogne23d5d372014-10-10 17:04:26 +02004273 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004274
Remi Gacogne23d5d372014-10-10 17:04:26 +02004275 if (ssl) {
4276 ciphers = SSL_get_ciphers(ssl);
4277
4278 if (ciphers) {
4279 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4280 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4281 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4282 if (strstr(cipher_description, dhe_description) != NULL ||
4283 strstr(cipher_description, dhe_export_description) != NULL) {
4284 dhe_found = 1;
4285 break;
4286 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004287 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004288 }
4289 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004290 SSL_free(ssl);
4291 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004292 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004293
Lukas Tribus90132722014-08-18 00:56:33 +02004294 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004295 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 +02004296 }
4297
Willy Tarreauef934602016-12-22 23:12:01 +01004298 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004299 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004300
Willy Tarreauef934602016-12-22 23:12:01 +01004301 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004302 if (local_dh_1024 == NULL) {
4303 local_dh_1024 = ssl_get_dh_1024();
4304 }
Willy Tarreauef934602016-12-22 23:12:01 +01004305 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004306 if (local_dh_2048 == NULL) {
4307 local_dh_2048 = ssl_get_dh_2048();
4308 }
Willy Tarreauef934602016-12-22 23:12:01 +01004309 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004310 if (local_dh_4096 == NULL) {
4311 local_dh_4096 = ssl_get_dh_4096();
4312 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004313 }
4314 }
4315 }
4316#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004317
Emeric Brunfc0421f2012-09-07 17:30:07 +02004318 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004319#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004320 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004321#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004322
Bernard Spil13c53f82018-02-15 13:34:58 +01004323#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004324 ssl_conf_cur = NULL;
4325 if (ssl_conf && ssl_conf->npn_str)
4326 ssl_conf_cur = ssl_conf;
4327 else if (bind_conf->ssl_conf.npn_str)
4328 ssl_conf_cur = &bind_conf->ssl_conf;
4329 if (ssl_conf_cur)
4330 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004331#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004332#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004333 ssl_conf_cur = NULL;
4334 if (ssl_conf && ssl_conf->alpn_str)
4335 ssl_conf_cur = ssl_conf;
4336 else if (bind_conf->ssl_conf.alpn_str)
4337 ssl_conf_cur = &bind_conf->ssl_conf;
4338 if (ssl_conf_cur)
4339 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004340#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004341#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4342 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4343 if (conf_curves) {
4344 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004345 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4346 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004347 cfgerr++;
4348 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004349#if defined(SSL_CTX_set_ecdh_auto)
4350 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4351#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004352 }
4353#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004354#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004355 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004356 int i;
4357 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004358#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004359 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004360 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4361 NULL);
4362
4363 if (ecdhe == NULL) {
4364 SSL_CTX_set_dh_auto(ctx, 1);
4365 return cfgerr;
4366 }
4367#else
4368 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4369 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4370 ECDHE_DEFAULT_CURVE);
4371#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004372
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004373 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004374 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004375 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4376 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004377 cfgerr++;
4378 }
4379 else {
4380 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4381 EC_KEY_free(ecdh);
4382 }
4383 }
4384#endif
4385
Emeric Brunfc0421f2012-09-07 17:30:07 +02004386 return cfgerr;
4387}
4388
Evan Broderbe554312013-06-27 00:05:25 -07004389static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4390{
4391 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4392 size_t prefixlen, suffixlen;
4393
4394 /* Trivial case */
4395 if (strcmp(pattern, hostname) == 0)
4396 return 1;
4397
Evan Broderbe554312013-06-27 00:05:25 -07004398 /* The rest of this logic is based on RFC 6125, section 6.4.3
4399 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4400
Emeric Bruna848dae2013-10-08 11:27:28 +02004401 pattern_wildcard = NULL;
4402 pattern_left_label_end = pattern;
4403 while (*pattern_left_label_end != '.') {
4404 switch (*pattern_left_label_end) {
4405 case 0:
4406 /* End of label not found */
4407 return 0;
4408 case '*':
4409 /* If there is more than one wildcards */
4410 if (pattern_wildcard)
4411 return 0;
4412 pattern_wildcard = pattern_left_label_end;
4413 break;
4414 }
4415 pattern_left_label_end++;
4416 }
4417
4418 /* If it's not trivial and there is no wildcard, it can't
4419 * match */
4420 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004421 return 0;
4422
4423 /* Make sure all labels match except the leftmost */
4424 hostname_left_label_end = strchr(hostname, '.');
4425 if (!hostname_left_label_end
4426 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4427 return 0;
4428
4429 /* Make sure the leftmost label of the hostname is long enough
4430 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004431 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004432 return 0;
4433
4434 /* Finally compare the string on either side of the
4435 * wildcard */
4436 prefixlen = pattern_wildcard - pattern;
4437 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004438 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4439 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004440 return 0;
4441
4442 return 1;
4443}
4444
4445static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4446{
4447 SSL *ssl;
4448 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004449 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004450 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004451
4452 int depth;
4453 X509 *cert;
4454 STACK_OF(GENERAL_NAME) *alt_names;
4455 int i;
4456 X509_NAME *cert_subject;
4457 char *str;
4458
4459 if (ok == 0)
4460 return ok;
4461
4462 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004463 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004464
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004465 /* We're checking if the provided hostnames match the desired one. The
4466 * desired hostname comes from the SNI we presented if any, or if not
4467 * provided then it may have been explicitly stated using a "verifyhost"
4468 * directive. If neither is set, we don't care about the name so the
4469 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004470 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004471 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004472 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004473 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004474 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004475 if (!servername)
4476 return ok;
4477 }
Evan Broderbe554312013-06-27 00:05:25 -07004478
4479 /* We only need to verify the CN on the actual server cert,
4480 * not the indirect CAs */
4481 depth = X509_STORE_CTX_get_error_depth(ctx);
4482 if (depth != 0)
4483 return ok;
4484
4485 /* At this point, the cert is *not* OK unless we can find a
4486 * hostname match */
4487 ok = 0;
4488
4489 cert = X509_STORE_CTX_get_current_cert(ctx);
4490 /* It seems like this might happen if verify peer isn't set */
4491 if (!cert)
4492 return ok;
4493
4494 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4495 if (alt_names) {
4496 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4497 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4498 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004499#if OPENSSL_VERSION_NUMBER < 0x00907000L
4500 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4501#else
Evan Broderbe554312013-06-27 00:05:25 -07004502 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004503#endif
Evan Broderbe554312013-06-27 00:05:25 -07004504 ok = ssl_sock_srv_hostcheck(str, servername);
4505 OPENSSL_free(str);
4506 }
4507 }
4508 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004509 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004510 }
4511
4512 cert_subject = X509_get_subject_name(cert);
4513 i = -1;
4514 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4515 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004516 ASN1_STRING *value;
4517 value = X509_NAME_ENTRY_get_data(entry);
4518 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004519 ok = ssl_sock_srv_hostcheck(str, servername);
4520 OPENSSL_free(str);
4521 }
4522 }
4523
Willy Tarreau71d058c2017-07-26 20:09:56 +02004524 /* report the mismatch and indicate if SNI was used or not */
4525 if (!ok && !conn->err_code)
4526 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004527 return ok;
4528}
4529
Emeric Brun94324a42012-10-11 14:00:19 +02004530/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004531int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004532{
Willy Tarreau03209342016-12-22 17:08:28 +01004533 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004534 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004535 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004536 SSL_OP_ALL | /* all known workarounds for bugs */
4537 SSL_OP_NO_SSLv2 |
4538 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004539 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004540 SSL_MODE_ENABLE_PARTIAL_WRITE |
4541 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004542 SSL_MODE_RELEASE_BUFFERS |
4543 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004544 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004545 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004546 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004547 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004548 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004549
Thierry Fournier383085f2013-01-24 14:15:43 +01004550 /* Make sure openssl opens /dev/urandom before the chroot */
4551 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004552 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004553 cfgerr++;
4554 }
4555
Willy Tarreaufce03112015-01-15 21:32:40 +01004556 /* Automatic memory computations need to know we use SSL there */
4557 global.ssl_used_backend = 1;
4558
4559 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004560 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004561 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004562 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4563 curproxy->id, srv->id,
4564 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004565 cfgerr++;
4566 return cfgerr;
4567 }
4568 }
Emeric Brun94324a42012-10-11 14:00:19 +02004569 if (srv->use_ssl)
4570 srv->xprt = &ssl_sock;
4571 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004572 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004573
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004574 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004575 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004576 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4577 proxy_type_str(curproxy), curproxy->id,
4578 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004579 cfgerr++;
4580 return cfgerr;
4581 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004582
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004583 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004584 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4585 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4586 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004587 else
4588 flags = conf_ssl_methods->flags;
4589
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004590 /* Real min and max should be determinate with configuration and openssl's capabilities */
4591 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004592 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004593 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004594 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004595
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004596 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004597 min = max = CONF_TLSV_NONE;
4598 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004599 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004600 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004601 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004602 if (min) {
4603 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004604 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4605 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4606 proxy_type_str(curproxy), curproxy->id, srv->id,
4607 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004608 hole = 0;
4609 }
4610 max = i;
4611 }
4612 else {
4613 min = max = i;
4614 }
4615 }
4616 else {
4617 if (min)
4618 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004619 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004620 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004621 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4622 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004623 cfgerr += 1;
4624 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004625
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004626#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004627 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004628 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004629 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004630 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004631 else
4632 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4633 if (flags & methodVersions[i].flag)
4634 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004635#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004636 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004637 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4638 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004639#endif
4640
4641 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4642 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004643 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004644
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004645#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004646 if (global_ssl.async)
4647 mode |= SSL_MODE_ASYNC;
4648#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004649 SSL_CTX_set_mode(ctx, mode);
4650 srv->ssl_ctx.ctx = ctx;
4651
Emeric Bruna7aa3092012-10-26 12:58:00 +02004652 if (srv->ssl_ctx.client_crt) {
4653 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 +01004654 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4655 proxy_type_str(curproxy), curproxy->id,
4656 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004657 cfgerr++;
4658 }
4659 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 +01004660 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4661 proxy_type_str(curproxy), curproxy->id,
4662 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004663 cfgerr++;
4664 }
4665 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004666 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4667 proxy_type_str(curproxy), curproxy->id,
4668 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004669 cfgerr++;
4670 }
4671 }
Emeric Brun94324a42012-10-11 14:00:19 +02004672
Emeric Brun850efd52014-01-29 12:24:34 +01004673 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4674 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004675 switch (srv->ssl_ctx.verify) {
4676 case SSL_SOCK_VERIFY_NONE:
4677 verify = SSL_VERIFY_NONE;
4678 break;
4679 case SSL_SOCK_VERIFY_REQUIRED:
4680 verify = SSL_VERIFY_PEER;
4681 break;
4682 }
Evan Broderbe554312013-06-27 00:05:25 -07004683 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004684 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004685 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004686 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004687 if (srv->ssl_ctx.ca_file) {
4688 /* load CAfile to verify */
4689 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004690 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4691 curproxy->id, srv->id,
4692 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004693 cfgerr++;
4694 }
4695 }
Emeric Brun850efd52014-01-29 12:24:34 +01004696 else {
4697 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004698 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",
4699 curproxy->id, srv->id,
4700 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004701 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004702 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4703 curproxy->id, srv->id,
4704 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004705 cfgerr++;
4706 }
Emeric Brunef42d922012-10-11 16:11:36 +02004707#ifdef X509_V_FLAG_CRL_CHECK
4708 if (srv->ssl_ctx.crl_file) {
4709 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4710
4711 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004712 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4713 curproxy->id, srv->id,
4714 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004715 cfgerr++;
4716 }
4717 else {
4718 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4719 }
4720 }
4721#endif
4722 }
4723
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004724 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4725 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4726 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004727 if (srv->ssl_ctx.ciphers &&
4728 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004729 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4730 curproxy->id, srv->id,
4731 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004732 cfgerr++;
4733 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004734
4735#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4736 if (srv->ssl_ctx.ciphersuites &&
4737 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4738 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4739 curproxy->id, srv->id,
4740 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4741 cfgerr++;
4742 }
4743#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004744#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4745 if (srv->ssl_ctx.npn_str)
4746 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4747#endif
4748#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4749 if (srv->ssl_ctx.alpn_str)
4750 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4751#endif
4752
Emeric Brun94324a42012-10-11 14:00:19 +02004753
4754 return cfgerr;
4755}
4756
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004757/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004758 * be NULL, in which case nothing is done. Returns the number of errors
4759 * encountered.
4760 */
Willy Tarreau03209342016-12-22 17:08:28 +01004761int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004762{
4763 struct ebmb_node *node;
4764 struct sni_ctx *sni;
4765 int err = 0;
4766
Willy Tarreaufce03112015-01-15 21:32:40 +01004767 /* Automatic memory computations need to know we use SSL there */
4768 global.ssl_used_frontend = 1;
4769
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004770 /* Make sure openssl opens /dev/urandom before the chroot */
4771 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004772 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004773 err++;
4774 }
4775 /* Create initial_ctx used to start the ssl connection before do switchctx */
4776 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004777 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004778 /* It should not be necessary to call this function, but it's
4779 necessary first to check and move all initialisation related
4780 to initial_ctx in ssl_sock_initial_ctx. */
4781 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4782 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004783 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004784 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004785
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004786 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004787 while (node) {
4788 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004789 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4790 /* only initialize the CTX on its first occurrence and
4791 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004792 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004793 node = ebmb_next(node);
4794 }
4795
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004796 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004797 while (node) {
4798 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004799 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4800 /* only initialize the CTX on its first occurrence and
4801 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004802 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004803 node = ebmb_next(node);
4804 }
4805 return err;
4806}
4807
Willy Tarreau55d37912016-12-21 23:38:39 +01004808/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4809 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4810 * alerts are directly emitted since the rest of the stack does it below.
4811 */
4812int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4813{
4814 struct proxy *px = bind_conf->frontend;
4815 int alloc_ctx;
4816 int err;
4817
4818 if (!bind_conf->is_ssl) {
4819 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004820 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4821 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004822 }
4823 return 0;
4824 }
4825 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004826 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004827 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4828 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004829 }
4830 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004831 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4832 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004833 return -1;
4834 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004835 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004836 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004837 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004838 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004839 sizeof(*sh_ssl_sess_tree),
4840 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004841 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004842 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4843 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");
4844 else
4845 ha_alert("Unable to allocate SSL session cache.\n");
4846 return -1;
4847 }
4848 /* free block callback */
4849 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4850 /* init the root tree within the extra space */
4851 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4852 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004853 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004854 err = 0;
4855 /* initialize all certificate contexts */
4856 err += ssl_sock_prepare_all_ctx(bind_conf);
4857
4858 /* initialize CA variables if the certificates generation is enabled */
4859 err += ssl_sock_load_ca(bind_conf);
4860
4861 return -err;
4862}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004863
4864/* release ssl context allocated for servers. */
4865void ssl_sock_free_srv_ctx(struct server *srv)
4866{
Olivier Houchardc7566002018-11-20 23:33:50 +01004867#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4868 if (srv->ssl_ctx.alpn_str)
4869 free(srv->ssl_ctx.alpn_str);
4870#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004871#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004872 if (srv->ssl_ctx.npn_str)
4873 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01004874#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004875 if (srv->ssl_ctx.ctx)
4876 SSL_CTX_free(srv->ssl_ctx.ctx);
4877}
4878
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004879/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004880 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4881 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004882void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004883{
4884 struct ebmb_node *node, *back;
4885 struct sni_ctx *sni;
4886
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004887 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004888 while (node) {
4889 sni = ebmb_entry(node, struct sni_ctx, name);
4890 back = ebmb_next(node);
4891 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004892 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004893 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004894 ssl_sock_free_ssl_conf(sni->conf);
4895 free(sni->conf);
4896 sni->conf = NULL;
4897 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004898 free(sni);
4899 node = back;
4900 }
4901
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004902 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004903 while (node) {
4904 sni = ebmb_entry(node, struct sni_ctx, name);
4905 back = ebmb_next(node);
4906 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004907 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004908 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004909 ssl_sock_free_ssl_conf(sni->conf);
4910 free(sni->conf);
4911 sni->conf = NULL;
4912 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004913 free(sni);
4914 node = back;
4915 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004916 SSL_CTX_free(bind_conf->initial_ctx);
4917 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004918 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004919 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004920}
4921
Willy Tarreau795cdab2016-12-22 17:30:54 +01004922/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4923void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4924{
4925 ssl_sock_free_ca(bind_conf);
4926 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004927 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004928 free(bind_conf->ca_sign_file);
4929 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004930 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004931 free(bind_conf->keys_ref->filename);
4932 free(bind_conf->keys_ref->tlskeys);
4933 LIST_DEL(&bind_conf->keys_ref->list);
4934 free(bind_conf->keys_ref);
4935 }
4936 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004937 bind_conf->ca_sign_pass = NULL;
4938 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004939}
4940
Christopher Faulet31af49d2015-06-09 17:29:50 +02004941/* Load CA cert file and private key used to generate certificates */
4942int
Willy Tarreau03209342016-12-22 17:08:28 +01004943ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004944{
Willy Tarreau03209342016-12-22 17:08:28 +01004945 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004946 FILE *fp;
4947 X509 *cacert = NULL;
4948 EVP_PKEY *capkey = NULL;
4949 int err = 0;
4950
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004951 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004952 return err;
4953
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004954#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004955 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004956 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004957 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004958 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004959 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004960#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004961
Christopher Faulet31af49d2015-06-09 17:29:50 +02004962 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004963 ha_alert("Proxy '%s': cannot enable certificate generation, "
4964 "no CA certificate File configured at [%s:%d].\n",
4965 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004966 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004967 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004968
4969 /* read in the CA certificate */
4970 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004971 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4972 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004973 goto load_error;
4974 }
4975 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004976 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4977 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004978 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004979 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004980 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004981 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004982 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4983 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004984 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004985 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004986
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004987 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004988 bind_conf->ca_sign_cert = cacert;
4989 bind_conf->ca_sign_pkey = capkey;
4990 return err;
4991
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004992 read_error:
4993 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004994 if (capkey) EVP_PKEY_free(capkey);
4995 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004996 load_error:
4997 bind_conf->generate_certs = 0;
4998 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004999 return err;
5000}
5001
5002/* Release CA cert and private key used to generate certificated */
5003void
5004ssl_sock_free_ca(struct bind_conf *bind_conf)
5005{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005006 if (bind_conf->ca_sign_pkey)
5007 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5008 if (bind_conf->ca_sign_cert)
5009 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005010 bind_conf->ca_sign_pkey = NULL;
5011 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005012}
5013
Emeric Brun46591952012-05-18 15:47:34 +02005014/*
5015 * This function is called if SSL * context is not yet allocated. The function
5016 * is designed to be called before any other data-layer operation and sets the
5017 * handshake flag on the connection. It is safe to call it multiple times.
5018 * It returns 0 on success and -1 in error case.
5019 */
5020static int ssl_sock_init(struct connection *conn)
5021{
5022 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005023 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005024 return 0;
5025
Willy Tarreau3c728722014-01-23 13:50:42 +01005026 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005027 return 0;
5028
Willy Tarreau20879a02012-12-03 16:32:10 +01005029 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5030 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005031 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005032 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005033
Emeric Brun46591952012-05-18 15:47:34 +02005034 /* If it is in client mode initiate SSL session
5035 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005036 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005037 int may_retry = 1;
5038
5039 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005040 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005041 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005042 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005043 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005044 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005045 goto retry_connect;
5046 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005047 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005048 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005049 }
Emeric Brun46591952012-05-18 15:47:34 +02005050
Emeric Brun46591952012-05-18 15:47:34 +02005051 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005052 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005053 SSL_free(conn->xprt_ctx);
5054 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005055 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005056 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005057 goto retry_connect;
5058 }
Emeric Brun55476152014-11-12 17:35:37 +01005059 conn->err_code = CO_ER_SSL_NO_MEM;
5060 return -1;
5061 }
Emeric Brun46591952012-05-18 15:47:34 +02005062
Evan Broderbe554312013-06-27 00:05:25 -07005063 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005064 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005065 SSL_free(conn->xprt_ctx);
5066 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005067 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005068 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005069 goto retry_connect;
5070 }
Emeric Brun55476152014-11-12 17:35:37 +01005071 conn->err_code = CO_ER_SSL_NO_MEM;
5072 return -1;
5073 }
5074
5075 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005076 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5077 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5078 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5079 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005080 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005081 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5082 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005083 } else if (sess) {
5084 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005085 }
5086 }
Evan Broderbe554312013-06-27 00:05:25 -07005087
Emeric Brun46591952012-05-18 15:47:34 +02005088 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005089 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005090
Emeric Brun7ad43e72018-10-10 14:51:02 +02005091 HA_ATOMIC_ADD(&sslconns, 1);
5092 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005093 return 0;
5094 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005095 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005096 int may_retry = 1;
5097
5098 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005099 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005100 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005101 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005102 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005103 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005104 goto retry_accept;
5105 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005106 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005107 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005108 }
Emeric Brun46591952012-05-18 15:47:34 +02005109
Emeric Brun46591952012-05-18 15:47:34 +02005110 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005111 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005112 SSL_free(conn->xprt_ctx);
5113 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005114 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005115 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005116 goto retry_accept;
5117 }
Emeric Brun55476152014-11-12 17:35:37 +01005118 conn->err_code = CO_ER_SSL_NO_MEM;
5119 return -1;
5120 }
Emeric Brun46591952012-05-18 15:47:34 +02005121
Emeric Brune1f38db2012-09-03 20:36:47 +02005122 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005123 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005124 SSL_free(conn->xprt_ctx);
5125 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005126 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005127 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005128 goto retry_accept;
5129 }
Emeric Brun55476152014-11-12 17:35:37 +01005130 conn->err_code = CO_ER_SSL_NO_MEM;
5131 return -1;
5132 }
5133
5134 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005135
Emeric Brun46591952012-05-18 15:47:34 +02005136 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005137 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005138#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005139 conn->flags |= CO_FL_EARLY_SSL_HS;
5140#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005141
Emeric Brun7ad43e72018-10-10 14:51:02 +02005142 HA_ATOMIC_ADD(&sslconns, 1);
5143 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005144 return 0;
5145 }
5146 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005147 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005148 return -1;
5149}
5150
5151
5152/* This is the callback which is used when an SSL handshake is pending. It
5153 * updates the FD status if it wants some polling before being called again.
5154 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5155 * otherwise it returns non-zero and removes itself from the connection's
5156 * flags (the bit is provided in <flag> by the caller).
5157 */
5158int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5159{
5160 int ret;
5161
Willy Tarreau3c728722014-01-23 13:50:42 +01005162 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005163 return 0;
5164
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005165 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005166 goto out_error;
5167
Olivier Houchardc2aae742017-09-22 18:26:28 +02005168#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5169 /*
5170 * Check if we have early data. If we do, we have to read them
5171 * before SSL_do_handshake() is called, And there's no way to
5172 * detect early data, except to try to read them
5173 */
5174 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5175 size_t read_data;
5176
5177 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5178 1, &read_data);
5179 if (ret == SSL_READ_EARLY_DATA_ERROR)
5180 goto check_error;
5181 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5182 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5183 return 1;
5184 } else
5185 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5186 }
5187#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005188 /* If we use SSL_do_handshake to process a reneg initiated by
5189 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5190 * Usually SSL_write and SSL_read are used and process implicitly
5191 * the reneg handshake.
5192 * Here we use SSL_peek as a workaround for reneg.
5193 */
5194 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5195 char c;
5196
5197 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5198 if (ret <= 0) {
5199 /* handshake may have not been completed, let's find why */
5200 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005201
Emeric Brun674b7432012-11-08 19:21:55 +01005202 if (ret == SSL_ERROR_WANT_WRITE) {
5203 /* SSL handshake needs to write, L4 connection may not be ready */
5204 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005205 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005206 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005207 return 0;
5208 }
5209 else if (ret == SSL_ERROR_WANT_READ) {
5210 /* handshake may have been completed but we have
5211 * no more data to read.
5212 */
5213 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5214 ret = 1;
5215 goto reneg_ok;
5216 }
5217 /* SSL handshake needs to read, L4 connection is ready */
5218 if (conn->flags & CO_FL_WAIT_L4_CONN)
5219 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5220 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005221 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005222 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005223 return 0;
5224 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005225#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005226 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005227 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005228 return 0;
5229 }
5230#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005231 else if (ret == SSL_ERROR_SYSCALL) {
5232 /* if errno is null, then connection was successfully established */
5233 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5234 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005235 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005236#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005237 conn->err_code = CO_ER_SSL_HANDSHAKE;
5238#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005239 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005240#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005241 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5242 empty_handshake = state == TLS_ST_BEFORE;
5243#else
5244 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5245#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005246 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005247 if (!errno) {
5248 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5249 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5250 else
5251 conn->err_code = CO_ER_SSL_EMPTY;
5252 }
5253 else {
5254 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5255 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5256 else
5257 conn->err_code = CO_ER_SSL_ABORT;
5258 }
5259 }
5260 else {
5261 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5262 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005263 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005264 conn->err_code = CO_ER_SSL_HANDSHAKE;
5265 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005266#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005267 }
Emeric Brun674b7432012-11-08 19:21:55 +01005268 goto out_error;
5269 }
5270 else {
5271 /* Fail on all other handshake errors */
5272 /* Note: OpenSSL may leave unread bytes in the socket's
5273 * buffer, causing an RST to be emitted upon close() on
5274 * TCP sockets. We first try to drain possibly pending
5275 * data to avoid this as much as possible.
5276 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005277 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005278 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005279 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5280 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005281 goto out_error;
5282 }
5283 }
5284 /* read some data: consider handshake completed */
5285 goto reneg_ok;
5286 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005287 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005288check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005289 if (ret != 1) {
5290 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005291 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005292
5293 if (ret == SSL_ERROR_WANT_WRITE) {
5294 /* SSL handshake needs to write, L4 connection may not be ready */
5295 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005296 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005297 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005298 return 0;
5299 }
5300 else if (ret == SSL_ERROR_WANT_READ) {
5301 /* SSL handshake needs to read, L4 connection is ready */
5302 if (conn->flags & CO_FL_WAIT_L4_CONN)
5303 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5304 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005305 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005306 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005307 return 0;
5308 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005309#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005310 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005311 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005312 return 0;
5313 }
5314#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005315 else if (ret == SSL_ERROR_SYSCALL) {
5316 /* if errno is null, then connection was successfully established */
5317 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5318 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005319 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005320#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005321 conn->err_code = CO_ER_SSL_HANDSHAKE;
5322#else
5323 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005324#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005325 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5326 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005327#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005328 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005329#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005330 if (empty_handshake) {
5331 if (!errno) {
5332 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5333 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5334 else
5335 conn->err_code = CO_ER_SSL_EMPTY;
5336 }
5337 else {
5338 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5339 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5340 else
5341 conn->err_code = CO_ER_SSL_ABORT;
5342 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005343 }
5344 else {
5345 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5346 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5347 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005348 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005349 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005350#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005351 }
Willy Tarreau89230192012-09-28 20:22:13 +02005352 goto out_error;
5353 }
Emeric Brun46591952012-05-18 15:47:34 +02005354 else {
5355 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005356 /* Note: OpenSSL may leave unread bytes in the socket's
5357 * buffer, causing an RST to be emitted upon close() on
5358 * TCP sockets. We first try to drain possibly pending
5359 * data to avoid this as much as possible.
5360 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005361 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005362 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005363 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5364 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005365 goto out_error;
5366 }
5367 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005368#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5369 else {
5370 /*
5371 * If the server refused the early data, we have to send a
5372 * 425 to the client, as we no longer have the data to sent
5373 * them again.
5374 */
5375 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5376 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5377 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5378 goto out_error;
5379 }
5380 }
5381 }
5382#endif
5383
Emeric Brun46591952012-05-18 15:47:34 +02005384
Emeric Brun674b7432012-11-08 19:21:55 +01005385reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005386
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005387#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005388 /* ASYNC engine API doesn't support moving read/write
5389 * buffers. So we disable ASYNC mode right after
5390 * the handshake to avoid buffer oveflows.
5391 */
5392 if (global_ssl.async)
5393 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5394#endif
Emeric Brun46591952012-05-18 15:47:34 +02005395 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005396 if (!SSL_session_reused(conn->xprt_ctx)) {
5397 if (objt_server(conn->target)) {
5398 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5399 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5400 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005401 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005402 else {
5403 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5404 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5405 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5406 }
Emeric Brun46591952012-05-18 15:47:34 +02005407 }
5408
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005409#ifdef OPENSSL_IS_BORINGSSL
5410 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5411 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5412#endif
Emeric Brun46591952012-05-18 15:47:34 +02005413 /* The connection is now established at both layers, it's time to leave */
5414 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5415 return 1;
5416
5417 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005418 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005419 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005420 ERR_clear_error();
5421
Emeric Brun9fa89732012-10-04 17:09:56 +02005422 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005423 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5424 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5425 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005426 }
5427
Emeric Brun46591952012-05-18 15:47:34 +02005428 /* Fail on all other handshake errors */
5429 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005430 if (!conn->err_code)
5431 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005432 return 0;
5433}
5434
5435/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005436 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005437 * buffer wraps, in which case a second call may be performed. The connection's
5438 * flags are updated with whatever special event is detected (error, read0,
5439 * empty). The caller is responsible for taking care of those events and
5440 * avoiding the call if inappropriate. The function does not call the
5441 * connection's polling update function, so the caller is responsible for this.
5442 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005443static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005444{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005445 ssize_t ret;
5446 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005447
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005448 conn_refresh_polling_flags(conn);
5449
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005450 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005451 goto out_error;
5452
5453 if (conn->flags & CO_FL_HANDSHAKE)
5454 /* a handshake was requested */
5455 return 0;
5456
Emeric Brun46591952012-05-18 15:47:34 +02005457 /* read the largest possible block. For this, we perform only one call
5458 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5459 * in which case we accept to do it once again. A new attempt is made on
5460 * EINTR too.
5461 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005462 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005463 int need_out = 0;
5464
Willy Tarreau591d4452018-06-15 17:21:00 +02005465 try = b_contig_space(buf);
5466 if (!try)
5467 break;
5468
Willy Tarreauabf08d92014-01-14 11:31:27 +01005469 if (try > count)
5470 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005471
Olivier Houchardc2aae742017-09-22 18:26:28 +02005472 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5473 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005474 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005475 done++;
5476 try--;
5477 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005478 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005479 conn->tmp_early_data = -1;
5480 continue;
5481 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005482
Olivier Houchardc2aae742017-09-22 18:26:28 +02005483#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5484 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5485 size_t read_length;
5486
5487 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005488 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005489 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5490 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005491 conn->flags |= CO_FL_EARLY_DATA;
5492 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5493 ret == SSL_READ_EARLY_DATA_FINISH) {
5494 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5495 /*
5496 * We're done reading the early data,
5497 * let's make the handshake
5498 */
5499 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5500 conn->flags |= CO_FL_SSL_WAIT_HS;
5501 need_out = 1;
5502 if (read_length == 0)
5503 break;
5504 }
5505 ret = read_length;
5506 }
5507 } else
5508#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005509 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005510#ifdef OPENSSL_IS_BORINGSSL
5511 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5512 if (SSL_in_early_data(conn->xprt_ctx)) {
5513 if (ret > 0)
5514 conn->flags |= CO_FL_EARLY_DATA;
5515 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005516 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005517 }
5518 }
5519#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005520 if (conn->flags & CO_FL_ERROR) {
5521 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005522 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005523 }
Emeric Brun46591952012-05-18 15:47:34 +02005524 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005525 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005526 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005527 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005528 }
Emeric Brun46591952012-05-18 15:47:34 +02005529 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005530 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005531 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005532 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005533 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005534 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005535#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005536 /* Async mode can be re-enabled, because we're leaving data state.*/
5537 if (global_ssl.async)
5538 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5539#endif
Emeric Brun46591952012-05-18 15:47:34 +02005540 break;
5541 }
5542 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005543 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5544 /* handshake is running, and it may need to re-enable read */
5545 conn->flags |= CO_FL_SSL_WAIT_HS;
5546 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005547#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005548 /* Async mode can be re-enabled, because we're leaving data state.*/
5549 if (global_ssl.async)
5550 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5551#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005552 break;
5553 }
Emeric Brun46591952012-05-18 15:47:34 +02005554 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005555 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005556 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005557 } else if (ret == SSL_ERROR_ZERO_RETURN)
5558 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005559 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5560 * stack before shutting down the connection for
5561 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005562 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5563 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005564 /* otherwise it's a real error */
5565 goto out_error;
5566 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005567 if (need_out)
5568 break;
Emeric Brun46591952012-05-18 15:47:34 +02005569 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005570 leave:
5571 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005572 return done;
5573
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005574 clear_ssl_error:
5575 /* Clear openssl global errors stack */
5576 ssl_sock_dump_errors(conn);
5577 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005578 read0:
5579 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005580 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005581
Emeric Brun46591952012-05-18 15:47:34 +02005582 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005583 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005584 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005585 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005586 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005587 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005588}
5589
5590
Willy Tarreau787db9a2018-06-14 18:31:46 +02005591/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5592 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5593 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005594 * Only one call to send() is performed, unless the buffer wraps, in which case
5595 * a second call may be performed. The connection's flags are updated with
5596 * whatever special event is detected (error, empty). The caller is responsible
5597 * for taking care of those events and avoiding the call if inappropriate. The
5598 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005599 * is responsible for this. The buffer's output is not adjusted, it's up to the
5600 * caller to take care of this. It's up to the caller to update the buffer's
5601 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005602 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005603static 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 +02005604{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005605 ssize_t ret;
5606 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005607
5608 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005609 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005610
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005611 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005612 goto out_error;
5613
5614 if (conn->flags & CO_FL_HANDSHAKE)
5615 /* a handshake was requested */
5616 return 0;
5617
5618 /* send the largest possible block. For this we perform only one call
5619 * to send() unless the buffer wraps and we exactly fill the first hunk,
5620 * in which case we accept to do it once again.
5621 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005622 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005623#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5624 size_t written_data;
5625#endif
5626
Willy Tarreau787db9a2018-06-14 18:31:46 +02005627 try = b_contig_data(buf, done);
5628 if (try > count)
5629 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005630
Willy Tarreau7bed9452014-02-02 02:00:24 +01005631 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005632 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005633 global_ssl.max_record && try > global_ssl.max_record) {
5634 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005635 }
5636 else {
5637 /* we need to keep the information about the fact that
5638 * we're not limiting the upcoming send(), because if it
5639 * fails, we'll have to retry with at least as many data.
5640 */
5641 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5642 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005643
Olivier Houchardc2aae742017-09-22 18:26:28 +02005644#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5645 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5646 unsigned int max_early;
5647
Olivier Houchard522eea72017-11-03 16:27:47 +01005648 if (objt_listener(conn->target))
5649 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5650 else {
5651 if (SSL_get0_session(conn->xprt_ctx))
5652 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5653 else
5654 max_early = 0;
5655 }
5656
Olivier Houchard90084a12017-11-23 18:21:29 +01005657 if (try + conn->sent_early_data > max_early) {
5658 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005659 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005660 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5661 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005662 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005663 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005664 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005665 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005666 if (ret == 1) {
5667 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005668 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005669 if (objt_server(conn->target)) {
5670 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5671 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5672 }
5673
Olivier Houchardc2aae742017-09-22 18:26:28 +02005674 }
5675
5676 } else
5677#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005678 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005679
Emeric Brune1f38db2012-09-03 20:36:47 +02005680 if (conn->flags & CO_FL_ERROR) {
5681 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005682 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005683 }
Emeric Brun46591952012-05-18 15:47:34 +02005684 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005685 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005686 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005687 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005688 }
5689 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005690 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005691
Emeric Brun46591952012-05-18 15:47:34 +02005692 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005693 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5694 /* handshake is running, and it may need to re-enable write */
5695 conn->flags |= CO_FL_SSL_WAIT_HS;
5696 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005697#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005698 /* Async mode can be re-enabled, because we're leaving data state.*/
5699 if (global_ssl.async)
5700 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5701#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005702 break;
5703 }
Emeric Brun46591952012-05-18 15:47:34 +02005704 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005705 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005706 break;
5707 }
5708 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005709 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005710 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005711 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005712#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005713 /* Async mode can be re-enabled, because we're leaving data state.*/
5714 if (global_ssl.async)
5715 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5716#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005717 break;
5718 }
Emeric Brun46591952012-05-18 15:47:34 +02005719 goto out_error;
5720 }
5721 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005722 leave:
5723 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005724 return done;
5725
5726 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005727 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005728 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005729 ERR_clear_error();
5730
Emeric Brun46591952012-05-18 15:47:34 +02005731 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005732 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005733}
5734
Emeric Brun46591952012-05-18 15:47:34 +02005735static void ssl_sock_close(struct connection *conn) {
5736
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005737 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005738#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005739 if (global_ssl.async) {
5740 OSSL_ASYNC_FD all_fd[32], afd;
5741 size_t num_all_fds = 0;
5742 int i;
5743
5744 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5745 if (num_all_fds > 32) {
5746 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5747 return;
5748 }
5749
5750 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5751
5752 /* If an async job is pending, we must try to
5753 to catch the end using polling before calling
5754 SSL_free */
5755 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5756 for (i=0 ; i < num_all_fds ; i++) {
5757 /* switch on an handler designed to
5758 * handle the SSL_free
5759 */
5760 afd = all_fd[i];
5761 fdtab[afd].iocb = ssl_async_fd_free;
5762 fdtab[afd].owner = conn->xprt_ctx;
5763 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005764 /* To ensure that the fd cache won't be used
5765 * and we'll catch a real RD event.
5766 */
5767 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005768 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005769 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005770 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005771 return;
5772 }
Emeric Brun3854e012017-05-17 20:42:48 +02005773 /* Else we can remove the fds from the fdtab
5774 * and call SSL_free.
5775 * note: we do a fd_remove and not a delete
5776 * because the fd is owned by the engine.
5777 * the engine is responsible to close
5778 */
5779 for (i=0 ; i < num_all_fds ; i++)
5780 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005781 }
5782#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005783 SSL_free(conn->xprt_ctx);
5784 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005785 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005786 }
Emeric Brun46591952012-05-18 15:47:34 +02005787}
5788
5789/* This function tries to perform a clean shutdown on an SSL connection, and in
5790 * any case, flags the connection as reusable if no handshake was in progress.
5791 */
5792static void ssl_sock_shutw(struct connection *conn, int clean)
5793{
5794 if (conn->flags & CO_FL_HANDSHAKE)
5795 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005796 if (!clean)
5797 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005798 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005799 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005800 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005801 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005802 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005803 ERR_clear_error();
5804 }
Emeric Brun46591952012-05-18 15:47:34 +02005805}
5806
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005807/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005808int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005809{
5810 struct pkey_info *pkinfo;
5811 int bits = 0;
5812 int sig = TLSEXT_signature_anonymous;
5813 int len = -1;
5814
5815 if (!ssl_sock_is_ssl(conn))
5816 return 0;
5817
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005818 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005819 if (pkinfo) {
5820 sig = pkinfo->sig;
5821 bits = pkinfo->bits;
5822 } else {
5823 /* multicert and generated cert have no pkey info */
5824 X509 *crt;
5825 EVP_PKEY *pkey;
5826 crt = SSL_get_certificate(conn->xprt_ctx);
5827 if (!crt)
5828 return 0;
5829 pkey = X509_get_pubkey(crt);
5830 if (pkey) {
5831 bits = EVP_PKEY_bits(pkey);
5832 switch(EVP_PKEY_base_id(pkey)) {
5833 case EVP_PKEY_RSA:
5834 sig = TLSEXT_signature_rsa;
5835 break;
5836 case EVP_PKEY_EC:
5837 sig = TLSEXT_signature_ecdsa;
5838 break;
5839 case EVP_PKEY_DSA:
5840 sig = TLSEXT_signature_dsa;
5841 break;
5842 }
5843 EVP_PKEY_free(pkey);
5844 }
5845 }
5846
5847 switch(sig) {
5848 case TLSEXT_signature_rsa:
5849 len = chunk_printf(out, "RSA%d", bits);
5850 break;
5851 case TLSEXT_signature_ecdsa:
5852 len = chunk_printf(out, "EC%d", bits);
5853 break;
5854 case TLSEXT_signature_dsa:
5855 len = chunk_printf(out, "DSA%d", bits);
5856 break;
5857 default:
5858 return 0;
5859 }
5860 if (len < 0)
5861 return 0;
5862 return 1;
5863}
5864
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005865/* used for ppv2 cert signature (can be used for logging) */
5866const char *ssl_sock_get_cert_sig(struct connection *conn)
5867{
5868 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5869 X509 *crt;
5870
5871 if (!ssl_sock_is_ssl(conn))
5872 return NULL;
5873 crt = SSL_get_certificate(conn->xprt_ctx);
5874 if (!crt)
5875 return NULL;
5876 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5877 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5878}
5879
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005880/* used for ppv2 authority */
5881const char *ssl_sock_get_sni(struct connection *conn)
5882{
5883#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5884 if (!ssl_sock_is_ssl(conn))
5885 return NULL;
5886 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5887#else
5888 return 0;
5889#endif
5890}
5891
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005892/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005893const char *ssl_sock_get_cipher_name(struct connection *conn)
5894{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005895 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005896 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005897
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005898 return SSL_get_cipher_name(conn->xprt_ctx);
5899}
5900
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005901/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005902const char *ssl_sock_get_proto_version(struct connection *conn)
5903{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005904 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005905 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005906
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005907 return SSL_get_version(conn->xprt_ctx);
5908}
5909
Willy Tarreau8d598402012-10-22 17:58:39 +02005910/* Extract a serial from a cert, and copy it to a chunk.
5911 * Returns 1 if serial is found and copied, 0 if no serial found and
5912 * -1 if output is not large enough.
5913 */
5914static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005915ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005916{
5917 ASN1_INTEGER *serial;
5918
5919 serial = X509_get_serialNumber(crt);
5920 if (!serial)
5921 return 0;
5922
5923 if (out->size < serial->length)
5924 return -1;
5925
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005926 memcpy(out->area, serial->data, serial->length);
5927 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005928 return 1;
5929}
5930
Emeric Brun43e79582014-10-29 19:03:26 +01005931/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005932 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5933 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005934 */
5935static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005936ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005937{
5938 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005939 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005940
5941 len =i2d_X509(crt, NULL);
5942 if (len <= 0)
5943 return 1;
5944
5945 if (out->size < len)
5946 return -1;
5947
5948 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005949 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005950 return 1;
5951}
5952
Emeric Brunce5ad802012-10-22 14:11:22 +02005953
Willy Tarreau83061a82018-07-13 11:56:34 +02005954/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005955 * Returns 1 if serial is found and copied, 0 if no valid time found
5956 * and -1 if output is not large enough.
5957 */
5958static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005959ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005960{
5961 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5962 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5963
5964 if (gentm->length < 12)
5965 return 0;
5966 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5967 return 0;
5968 if (out->size < gentm->length-2)
5969 return -1;
5970
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005971 memcpy(out->area, gentm->data+2, gentm->length-2);
5972 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005973 return 1;
5974 }
5975 else if (tm->type == V_ASN1_UTCTIME) {
5976 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5977
5978 if (utctm->length < 10)
5979 return 0;
5980 if (utctm->data[0] >= 0x35)
5981 return 0;
5982 if (out->size < utctm->length)
5983 return -1;
5984
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005985 memcpy(out->area, utctm->data, utctm->length);
5986 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005987 return 1;
5988 }
5989
5990 return 0;
5991}
5992
Emeric Brun87855892012-10-17 17:39:35 +02005993/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5994 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5995 */
5996static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005997ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5998 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005999{
6000 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006001 ASN1_OBJECT *obj;
6002 ASN1_STRING *data;
6003 const unsigned char *data_ptr;
6004 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006005 int i, j, n;
6006 int cur = 0;
6007 const char *s;
6008 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006009 int name_count;
6010
6011 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006012
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006013 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006014 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006015 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006016 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006017 else
6018 j = i;
6019
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006020 ne = X509_NAME_get_entry(a, j);
6021 obj = X509_NAME_ENTRY_get_object(ne);
6022 data = X509_NAME_ENTRY_get_data(ne);
6023 data_ptr = ASN1_STRING_get0_data(data);
6024 data_len = ASN1_STRING_length(data);
6025 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006026 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006027 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006028 s = tmp;
6029 }
6030
6031 if (chunk_strcasecmp(entry, s) != 0)
6032 continue;
6033
6034 if (pos < 0)
6035 cur--;
6036 else
6037 cur++;
6038
6039 if (cur != pos)
6040 continue;
6041
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006042 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006043 return -1;
6044
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006045 memcpy(out->area, data_ptr, data_len);
6046 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006047 return 1;
6048 }
6049
6050 return 0;
6051
6052}
6053
6054/* Extract and format full DN from a X509_NAME and copy result into a chunk
6055 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6056 */
6057static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006058ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006059{
6060 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006061 ASN1_OBJECT *obj;
6062 ASN1_STRING *data;
6063 const unsigned char *data_ptr;
6064 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006065 int i, n, ln;
6066 int l = 0;
6067 const char *s;
6068 char *p;
6069 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006070 int name_count;
6071
6072
6073 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006074
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006075 out->data = 0;
6076 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006077 for (i = 0; i < name_count; i++) {
6078 ne = X509_NAME_get_entry(a, i);
6079 obj = X509_NAME_ENTRY_get_object(ne);
6080 data = X509_NAME_ENTRY_get_data(ne);
6081 data_ptr = ASN1_STRING_get0_data(data);
6082 data_len = ASN1_STRING_length(data);
6083 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006084 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006085 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006086 s = tmp;
6087 }
6088 ln = strlen(s);
6089
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006090 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006091 if (l > out->size)
6092 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006093 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006094
6095 *(p++)='/';
6096 memcpy(p, s, ln);
6097 p += ln;
6098 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006099 memcpy(p, data_ptr, data_len);
6100 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006101 }
6102
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006103 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006104 return 0;
6105
6106 return 1;
6107}
6108
Olivier Houchardab28a322018-12-21 19:45:40 +01006109void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6110{
6111#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6112 SSL_set_alpn_protos(conn->xprt_ctx, alpn, len);
6113#endif
6114}
6115
Willy Tarreau119a4082016-12-22 21:58:38 +01006116/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6117 * to disable SNI.
6118 */
Willy Tarreau63076412015-07-10 11:33:32 +02006119void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6120{
6121#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006122 char *prev_name;
6123
Willy Tarreau63076412015-07-10 11:33:32 +02006124 if (!ssl_sock_is_ssl(conn))
6125 return;
6126
Willy Tarreau119a4082016-12-22 21:58:38 +01006127 /* if the SNI changes, we must destroy the reusable context so that a
6128 * new connection will present a new SNI. As an optimization we could
6129 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6130 * server.
6131 */
6132 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6133 if ((!prev_name && hostname) ||
6134 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6135 SSL_set_session(conn->xprt_ctx, NULL);
6136
Willy Tarreau63076412015-07-10 11:33:32 +02006137 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6138#endif
6139}
6140
Emeric Brun0abf8362014-06-24 18:26:41 +02006141/* Extract peer certificate's common name into the chunk dest
6142 * Returns
6143 * the len of the extracted common name
6144 * or 0 if no CN found in DN
6145 * or -1 on error case (i.e. no peer certificate)
6146 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006147int ssl_sock_get_remote_common_name(struct connection *conn,
6148 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006149{
6150 X509 *crt = NULL;
6151 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006152 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006153 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006154 .area = (char *)&find_cn,
6155 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006156 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006157 int result = -1;
David Safb76832014-05-08 23:42:08 -04006158
6159 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006160 goto out;
David Safb76832014-05-08 23:42:08 -04006161
6162 /* SSL_get_peer_certificate, it increase X509 * ref count */
6163 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6164 if (!crt)
6165 goto out;
6166
6167 name = X509_get_subject_name(crt);
6168 if (!name)
6169 goto out;
David Safb76832014-05-08 23:42:08 -04006170
Emeric Brun0abf8362014-06-24 18:26:41 +02006171 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6172out:
David Safb76832014-05-08 23:42:08 -04006173 if (crt)
6174 X509_free(crt);
6175
6176 return result;
6177}
6178
Dave McCowan328fb582014-07-30 10:39:13 -04006179/* returns 1 if client passed a certificate for this session, 0 if not */
6180int ssl_sock_get_cert_used_sess(struct connection *conn)
6181{
6182 X509 *crt = NULL;
6183
6184 if (!ssl_sock_is_ssl(conn))
6185 return 0;
6186
6187 /* SSL_get_peer_certificate, it increase X509 * ref count */
6188 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6189 if (!crt)
6190 return 0;
6191
6192 X509_free(crt);
6193 return 1;
6194}
6195
6196/* returns 1 if client passed a certificate for this connection, 0 if not */
6197int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006198{
6199 if (!ssl_sock_is_ssl(conn))
6200 return 0;
6201
6202 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6203}
6204
6205/* returns result from SSL verify */
6206unsigned int ssl_sock_get_verify_result(struct connection *conn)
6207{
6208 if (!ssl_sock_is_ssl(conn))
6209 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6210
6211 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6212}
6213
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006214/* Returns the application layer protocol name in <str> and <len> when known.
6215 * Zero is returned if the protocol name was not found, otherwise non-zero is
6216 * returned. The string is allocated in the SSL context and doesn't have to be
6217 * freed by the caller. NPN is also checked if available since older versions
6218 * of openssl (1.0.1) which are more common in field only support this one.
6219 */
6220static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6221{
6222 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6223 return 0;
6224
6225 *str = NULL;
6226
6227#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6228 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6229 if (*str)
6230 return 1;
6231#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006232#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006233 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6234 if (*str)
6235 return 1;
6236#endif
6237 return 0;
6238}
6239
Willy Tarreau7875d092012-09-10 08:20:03 +02006240/***** Below are some sample fetching functions for ACL/patterns *****/
6241
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006242static int
6243smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6244{
6245 struct connection *conn;
6246
6247 conn = objt_conn(smp->sess->origin);
6248 if (!conn || conn->xprt != &ssl_sock)
6249 return 0;
6250
6251 smp->flags = 0;
6252 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006253 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6254 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006255
6256 return 1;
6257}
6258
Emeric Brune64aef12012-09-21 13:15:06 +02006259/* boolean, returns true if client cert was present */
6260static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006261smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006262{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006263 struct connection *conn;
6264
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006265 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006266 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006267 return 0;
6268
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006269 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006270 smp->flags |= SMP_F_MAY_CHANGE;
6271 return 0;
6272 }
6273
6274 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006275 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006276 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006277
6278 return 1;
6279}
6280
Emeric Brun43e79582014-10-29 19:03:26 +01006281/* binary, returns a certificate in a binary chunk (der/raw).
6282 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6283 * should be use.
6284 */
6285static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006286smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006287{
6288 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6289 X509 *crt = NULL;
6290 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006291 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006292 struct connection *conn;
6293
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006294 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006295 if (!conn || conn->xprt != &ssl_sock)
6296 return 0;
6297
6298 if (!(conn->flags & CO_FL_CONNECTED)) {
6299 smp->flags |= SMP_F_MAY_CHANGE;
6300 return 0;
6301 }
6302
6303 if (cert_peer)
6304 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6305 else
6306 crt = SSL_get_certificate(conn->xprt_ctx);
6307
6308 if (!crt)
6309 goto out;
6310
6311 smp_trash = get_trash_chunk();
6312 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6313 goto out;
6314
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006315 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006316 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006317 ret = 1;
6318out:
6319 /* SSL_get_peer_certificate, it increase X509 * ref count */
6320 if (cert_peer && crt)
6321 X509_free(crt);
6322 return ret;
6323}
6324
Emeric Brunba841a12014-04-30 17:05:08 +02006325/* binary, returns serial of certificate in a binary chunk.
6326 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6327 * should be use.
6328 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006329static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006330smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006331{
Emeric Brunba841a12014-04-30 17:05:08 +02006332 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006333 X509 *crt = NULL;
6334 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006335 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006336 struct connection *conn;
6337
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006338 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006339 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006340 return 0;
6341
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006342 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006343 smp->flags |= SMP_F_MAY_CHANGE;
6344 return 0;
6345 }
6346
Emeric Brunba841a12014-04-30 17:05:08 +02006347 if (cert_peer)
6348 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6349 else
6350 crt = SSL_get_certificate(conn->xprt_ctx);
6351
Willy Tarreau8d598402012-10-22 17:58:39 +02006352 if (!crt)
6353 goto out;
6354
Willy Tarreau47ca5452012-12-23 20:22:19 +01006355 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006356 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6357 goto out;
6358
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006359 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006360 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006361 ret = 1;
6362out:
Emeric Brunba841a12014-04-30 17:05:08 +02006363 /* SSL_get_peer_certificate, it increase X509 * ref count */
6364 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006365 X509_free(crt);
6366 return ret;
6367}
Emeric Brune64aef12012-09-21 13:15:06 +02006368
Emeric Brunba841a12014-04-30 17:05:08 +02006369/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6370 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6371 * should be use.
6372 */
James Votha051b4a2013-05-14 20:37:59 +02006373static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006374smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006375{
Emeric Brunba841a12014-04-30 17:05:08 +02006376 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006377 X509 *crt = NULL;
6378 const EVP_MD *digest;
6379 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006380 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006381 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006382
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006383 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006384 if (!conn || conn->xprt != &ssl_sock)
6385 return 0;
6386
6387 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006388 smp->flags |= SMP_F_MAY_CHANGE;
6389 return 0;
6390 }
6391
Emeric Brunba841a12014-04-30 17:05:08 +02006392 if (cert_peer)
6393 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6394 else
6395 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006396 if (!crt)
6397 goto out;
6398
6399 smp_trash = get_trash_chunk();
6400 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006401 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6402 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006403
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006404 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006405 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006406 ret = 1;
6407out:
Emeric Brunba841a12014-04-30 17:05:08 +02006408 /* SSL_get_peer_certificate, it increase X509 * ref count */
6409 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006410 X509_free(crt);
6411 return ret;
6412}
6413
Emeric Brunba841a12014-04-30 17:05:08 +02006414/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6415 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6416 * should be use.
6417 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006418static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006419smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006420{
Emeric Brunba841a12014-04-30 17:05:08 +02006421 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006422 X509 *crt = NULL;
6423 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006424 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006425 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006426
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006427 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006428 if (!conn || conn->xprt != &ssl_sock)
6429 return 0;
6430
6431 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006432 smp->flags |= SMP_F_MAY_CHANGE;
6433 return 0;
6434 }
6435
Emeric Brunba841a12014-04-30 17:05:08 +02006436 if (cert_peer)
6437 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6438 else
6439 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006440 if (!crt)
6441 goto out;
6442
Willy Tarreau47ca5452012-12-23 20:22:19 +01006443 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006444 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006445 goto out;
6446
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006447 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006448 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006449 ret = 1;
6450out:
Emeric Brunba841a12014-04-30 17:05:08 +02006451 /* SSL_get_peer_certificate, it increase X509 * ref count */
6452 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006453 X509_free(crt);
6454 return ret;
6455}
6456
Emeric Brunba841a12014-04-30 17:05:08 +02006457/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6458 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6459 * should be use.
6460 */
Emeric Brun87855892012-10-17 17:39:35 +02006461static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006462smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006463{
Emeric Brunba841a12014-04-30 17:05:08 +02006464 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006465 X509 *crt = NULL;
6466 X509_NAME *name;
6467 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006468 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006469 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006470
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006471 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006472 if (!conn || conn->xprt != &ssl_sock)
6473 return 0;
6474
6475 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006476 smp->flags |= SMP_F_MAY_CHANGE;
6477 return 0;
6478 }
6479
Emeric Brunba841a12014-04-30 17:05:08 +02006480 if (cert_peer)
6481 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6482 else
6483 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006484 if (!crt)
6485 goto out;
6486
6487 name = X509_get_issuer_name(crt);
6488 if (!name)
6489 goto out;
6490
Willy Tarreau47ca5452012-12-23 20:22:19 +01006491 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006492 if (args && args[0].type == ARGT_STR) {
6493 int pos = 1;
6494
6495 if (args[1].type == ARGT_SINT)
6496 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006497
6498 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6499 goto out;
6500 }
6501 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6502 goto out;
6503
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006504 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006505 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006506 ret = 1;
6507out:
Emeric Brunba841a12014-04-30 17:05:08 +02006508 /* SSL_get_peer_certificate, it increase X509 * ref count */
6509 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006510 X509_free(crt);
6511 return ret;
6512}
6513
Emeric Brunba841a12014-04-30 17:05:08 +02006514/* string, returns notbefore date in ASN1_UTCTIME format.
6515 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6516 * should be use.
6517 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006518static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006519smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006520{
Emeric Brunba841a12014-04-30 17:05:08 +02006521 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006522 X509 *crt = NULL;
6523 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006524 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006525 struct connection *conn;
6526
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006527 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006528 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006529 return 0;
6530
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006531 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006532 smp->flags |= SMP_F_MAY_CHANGE;
6533 return 0;
6534 }
6535
Emeric Brunba841a12014-04-30 17:05:08 +02006536 if (cert_peer)
6537 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6538 else
6539 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006540 if (!crt)
6541 goto out;
6542
Willy Tarreau47ca5452012-12-23 20:22:19 +01006543 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006544 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006545 goto out;
6546
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006547 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006548 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006549 ret = 1;
6550out:
Emeric Brunba841a12014-04-30 17:05:08 +02006551 /* SSL_get_peer_certificate, it increase X509 * ref count */
6552 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006553 X509_free(crt);
6554 return ret;
6555}
6556
Emeric Brunba841a12014-04-30 17:05:08 +02006557/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6558 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6559 * should be use.
6560 */
Emeric Brun87855892012-10-17 17:39:35 +02006561static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006562smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006563{
Emeric Brunba841a12014-04-30 17:05:08 +02006564 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006565 X509 *crt = NULL;
6566 X509_NAME *name;
6567 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006568 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006569 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006570
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006571 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006572 if (!conn || conn->xprt != &ssl_sock)
6573 return 0;
6574
6575 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006576 smp->flags |= SMP_F_MAY_CHANGE;
6577 return 0;
6578 }
6579
Emeric Brunba841a12014-04-30 17:05:08 +02006580 if (cert_peer)
6581 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6582 else
6583 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006584 if (!crt)
6585 goto out;
6586
6587 name = X509_get_subject_name(crt);
6588 if (!name)
6589 goto out;
6590
Willy Tarreau47ca5452012-12-23 20:22:19 +01006591 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006592 if (args && args[0].type == ARGT_STR) {
6593 int pos = 1;
6594
6595 if (args[1].type == ARGT_SINT)
6596 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006597
6598 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6599 goto out;
6600 }
6601 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6602 goto out;
6603
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006604 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006605 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006606 ret = 1;
6607out:
Emeric Brunba841a12014-04-30 17:05:08 +02006608 /* SSL_get_peer_certificate, it increase X509 * ref count */
6609 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006610 X509_free(crt);
6611 return ret;
6612}
Emeric Brun9143d372012-12-20 15:44:16 +01006613
6614/* integer, returns true if current session use a client certificate */
6615static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006616smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006617{
6618 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006619 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006620
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006621 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006622 if (!conn || conn->xprt != &ssl_sock)
6623 return 0;
6624
6625 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006626 smp->flags |= SMP_F_MAY_CHANGE;
6627 return 0;
6628 }
6629
6630 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006631 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006632 if (crt) {
6633 X509_free(crt);
6634 }
6635
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006636 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006637 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006638 return 1;
6639}
6640
Emeric Brunba841a12014-04-30 17:05:08 +02006641/* integer, returns the certificate version
6642 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6643 * should be use.
6644 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006645static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006646smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006647{
Emeric Brunba841a12014-04-30 17:05:08 +02006648 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006649 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006650 struct connection *conn;
6651
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006652 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006653 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006654 return 0;
6655
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006656 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006657 smp->flags |= SMP_F_MAY_CHANGE;
6658 return 0;
6659 }
6660
Emeric Brunba841a12014-04-30 17:05:08 +02006661 if (cert_peer)
6662 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6663 else
6664 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006665 if (!crt)
6666 return 0;
6667
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006668 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006669 /* SSL_get_peer_certificate increase X509 * ref count */
6670 if (cert_peer)
6671 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006672 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006673
6674 return 1;
6675}
6676
Emeric Brunba841a12014-04-30 17:05:08 +02006677/* string, returns the certificate's signature algorithm.
6678 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6679 * should be use.
6680 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006681static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006682smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006683{
Emeric Brunba841a12014-04-30 17:05:08 +02006684 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006685 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006686 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006687 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006688 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006689
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006690 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006691 if (!conn || conn->xprt != &ssl_sock)
6692 return 0;
6693
6694 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006695 smp->flags |= SMP_F_MAY_CHANGE;
6696 return 0;
6697 }
6698
Emeric Brunba841a12014-04-30 17:05:08 +02006699 if (cert_peer)
6700 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6701 else
6702 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006703 if (!crt)
6704 return 0;
6705
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006706 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6707 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006708
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006709 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6710 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006711 /* SSL_get_peer_certificate increase X509 * ref count */
6712 if (cert_peer)
6713 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006714 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006715 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006716
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006717 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006718 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006719 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006720 /* SSL_get_peer_certificate increase X509 * ref count */
6721 if (cert_peer)
6722 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006723
6724 return 1;
6725}
6726
Emeric Brunba841a12014-04-30 17:05:08 +02006727/* string, returns the certificate's key algorithm.
6728 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6729 * should be use.
6730 */
Emeric Brun521a0112012-10-22 12:22:55 +02006731static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006732smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006733{
Emeric Brunba841a12014-04-30 17:05:08 +02006734 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006735 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006736 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006737 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006738 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006739
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006740 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006741 if (!conn || conn->xprt != &ssl_sock)
6742 return 0;
6743
6744 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006745 smp->flags |= SMP_F_MAY_CHANGE;
6746 return 0;
6747 }
6748
Emeric Brunba841a12014-04-30 17:05:08 +02006749 if (cert_peer)
6750 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6751 else
6752 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006753 if (!crt)
6754 return 0;
6755
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006756 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6757 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006758
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006759 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6760 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006761 /* SSL_get_peer_certificate increase X509 * ref count */
6762 if (cert_peer)
6763 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006764 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006765 }
Emeric Brun521a0112012-10-22 12:22:55 +02006766
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006767 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006768 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006769 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006770 if (cert_peer)
6771 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006772
6773 return 1;
6774}
6775
Emeric Brun645ae792014-04-30 14:21:06 +02006776/* boolean, returns true if front conn. transport layer is SSL.
6777 * This function is also usable on backend conn if the fetch keyword 5th
6778 * char is 'b'.
6779 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006780static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006781smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006782{
Emeric Bruneb8def92018-02-19 15:59:48 +01006783 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6784 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006785
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006786 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006787 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006788 return 1;
6789}
6790
Emeric Brun2525b6b2012-10-18 15:59:43 +02006791/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006792static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006793smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006794{
6795#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006796 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006797
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006798 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006799 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006800 conn->xprt_ctx &&
6801 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006802 return 1;
6803#else
6804 return 0;
6805#endif
6806}
6807
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006808/* boolean, returns true if client session has been resumed.
6809 * This function is also usable on backend conn if the fetch keyword 5th
6810 * char is 'b'.
6811 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006812static int
6813smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6814{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006815 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6816 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6817
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006818
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006819 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006820 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006821 conn->xprt_ctx &&
6822 SSL_session_reused(conn->xprt_ctx);
6823 return 1;
6824}
6825
Emeric Brun645ae792014-04-30 14:21:06 +02006826/* string, returns the used cipher if front conn. transport layer is SSL.
6827 * This function is also usable on backend conn if the fetch keyword 5th
6828 * char is 'b'.
6829 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006830static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006831smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006832{
Emeric Bruneb8def92018-02-19 15:59:48 +01006833 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6834 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006835
Willy Tarreaube508f12016-03-10 11:47:01 +01006836 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006837 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006838 return 0;
6839
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006840 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6841 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006842 return 0;
6843
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006844 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006845 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006846 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006847
6848 return 1;
6849}
6850
Emeric Brun645ae792014-04-30 14:21:06 +02006851/* integer, returns the algoritm's keysize if front conn. transport layer
6852 * is SSL.
6853 * This function is also usable on backend conn if the fetch keyword 5th
6854 * char is 'b'.
6855 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006856static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006857smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006858{
Emeric Bruneb8def92018-02-19 15:59:48 +01006859 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6860 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006861 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006862
Emeric Brun589fcad2012-10-16 14:13:26 +02006863 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006864 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006865 return 0;
6866
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006867 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006868 return 0;
6869
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006870 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006871 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006872
6873 return 1;
6874}
6875
Emeric Brun645ae792014-04-30 14:21:06 +02006876/* integer, returns the used keysize if front conn. transport layer is SSL.
6877 * This function is also usable on backend conn if the fetch keyword 5th
6878 * char is 'b'.
6879 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006880static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006881smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006882{
Emeric Bruneb8def92018-02-19 15:59:48 +01006883 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6884 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006885
Emeric Brun589fcad2012-10-16 14:13:26 +02006886 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006887 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6888 return 0;
6889
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006890 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6891 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006892 return 0;
6893
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006894 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006895
6896 return 1;
6897}
6898
Bernard Spil13c53f82018-02-15 13:34:58 +01006899#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006900static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006901smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006902{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006903 struct connection *conn;
6904
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006905 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006906 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006907
Olivier Houchard6b77f492018-11-22 18:18:29 +01006908 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6909 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006910 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6911 return 0;
6912
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006913 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006914 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006915 (const unsigned char **)&smp->data.u.str.area,
6916 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006917
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006918 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006919 return 0;
6920
6921 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006922}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006923#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006924
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006925#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006926static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006927smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006928{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006929 struct connection *conn;
6930
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006931 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006932 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006933
Olivier Houchard6b77f492018-11-22 18:18:29 +01006934 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6935 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6936
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006937 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006938 return 0;
6939
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006940 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006941 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006942 (const unsigned char **)&smp->data.u.str.area,
6943 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006944
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006945 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006946 return 0;
6947
6948 return 1;
6949}
6950#endif
6951
Emeric Brun645ae792014-04-30 14:21:06 +02006952/* string, returns the used protocol if front conn. transport layer is SSL.
6953 * This function is also usable on backend conn if the fetch keyword 5th
6954 * char is 'b'.
6955 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006956static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006957smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006958{
Emeric Bruneb8def92018-02-19 15:59:48 +01006959 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6960 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006961
Emeric Brun589fcad2012-10-16 14:13:26 +02006962 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006963 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6964 return 0;
6965
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006966 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6967 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006968 return 0;
6969
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006970 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006971 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006972 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006973
6974 return 1;
6975}
6976
Willy Tarreau87b09662015-04-03 00:22:06 +02006977/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006978 * This function is also usable on backend conn if the fetch keyword 5th
6979 * char is 'b'.
6980 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006981#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006982static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006983smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006984{
Emeric Bruneb8def92018-02-19 15:59:48 +01006985 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6986 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006987 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006988
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006989 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006990 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006991
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006992 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6993 return 0;
6994
Willy Tarreau192252e2015-04-04 01:47:55 +02006995 ssl_sess = SSL_get_session(conn->xprt_ctx);
6996 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006997 return 0;
6998
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006999 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7000 (unsigned int *)&smp->data.u.str.data);
7001 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007002 return 0;
7003
7004 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007005}
Patrick Hemmer41966772018-04-28 19:15:48 -04007006#endif
7007
Emeric Brunfe68f682012-10-16 14:59:28 +02007008
Patrick Hemmere0275472018-04-28 19:15:51 -04007009#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
7010static int
7011smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7012{
7013 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7014 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7015 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007016 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04007017
7018 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7019 return 0;
7020
7021 ssl_sess = SSL_get_session(conn->xprt_ctx);
7022 if (!ssl_sess)
7023 return 0;
7024
7025 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007026 data->data = SSL_SESSION_get_master_key(ssl_sess,
7027 (unsigned char *) data->area,
7028 data->size);
7029 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007030 return 0;
7031
7032 smp->flags = 0;
7033 smp->data.type = SMP_T_BIN;
7034 smp->data.u.str = *data;
7035
7036 return 1;
7037}
7038#endif
7039
Patrick Hemmer41966772018-04-28 19:15:48 -04007040#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007041static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007042smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007043{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007044 struct connection *conn;
7045
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007046 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007047 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007048
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007049 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007050 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7051 return 0;
7052
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007053 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7054 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007055 return 0;
7056
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007057 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007058 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007059}
Patrick Hemmer41966772018-04-28 19:15:48 -04007060#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007061
David Sc1ad52e2014-04-08 18:48:47 -04007062static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007063smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7064{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007065 struct connection *conn;
7066 struct ssl_capture *capture;
7067
7068 conn = objt_conn(smp->sess->origin);
7069 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7070 return 0;
7071
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007072 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007073 if (!capture)
7074 return 0;
7075
7076 smp->flags = SMP_F_CONST;
7077 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007078 smp->data.u.str.area = capture->ciphersuite;
7079 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007080 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007081}
7082
7083static int
7084smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7085{
Willy Tarreau83061a82018-07-13 11:56:34 +02007086 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007087
7088 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7089 return 0;
7090
7091 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007092 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007093 smp->data.type = SMP_T_BIN;
7094 smp->data.u.str = *data;
7095 return 1;
7096}
7097
7098static int
7099smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7100{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007101 struct connection *conn;
7102 struct ssl_capture *capture;
7103
7104 conn = objt_conn(smp->sess->origin);
7105 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7106 return 0;
7107
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007108 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007109 if (!capture)
7110 return 0;
7111
7112 smp->data.type = SMP_T_SINT;
7113 smp->data.u.sint = capture->xxh64;
7114 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007115}
7116
7117static int
7118smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7119{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007120#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007121 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007122 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007123
7124 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7125 return 0;
7126
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007127 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007128 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007129 const char *str;
7130 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007131 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007132 uint16_t id = (bin[0] << 8) | bin[1];
7133#if defined(OPENSSL_IS_BORINGSSL)
7134 cipher = SSL_get_cipher_by_value(id);
7135#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007136 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007137 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7138#endif
7139 str = SSL_CIPHER_get_name(cipher);
7140 if (!str || strcmp(str, "(NONE)") == 0)
7141 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007142 else
7143 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7144 }
7145 smp->data.type = SMP_T_STR;
7146 smp->data.u.str = *data;
7147 return 1;
7148#else
7149 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7150#endif
7151}
7152
Patrick Hemmer41966772018-04-28 19:15:48 -04007153#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007154static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007155smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007156{
Emeric Bruneb8def92018-02-19 15:59:48 +01007157 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7158 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007159 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007160 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007161
7162 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007163 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7164 return 0;
7165
7166 if (!(conn->flags & CO_FL_CONNECTED)) {
7167 smp->flags |= SMP_F_MAY_CHANGE;
7168 return 0;
7169 }
7170
7171 finished_trash = get_trash_chunk();
7172 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007173 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7174 finished_trash->area,
7175 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007176 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007177 finished_len = SSL_get_finished(conn->xprt_ctx,
7178 finished_trash->area,
7179 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007180
7181 if (!finished_len)
7182 return 0;
7183
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007184 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007185 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007186 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007187
7188 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007189}
Patrick Hemmer41966772018-04-28 19:15:48 -04007190#endif
David Sc1ad52e2014-04-08 18:48:47 -04007191
Emeric Brun2525b6b2012-10-18 15:59:43 +02007192/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007193static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007194smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007195{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007196 struct connection *conn;
7197
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007198 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007199 if (!conn || conn->xprt != &ssl_sock)
7200 return 0;
7201
7202 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007203 smp->flags = SMP_F_MAY_CHANGE;
7204 return 0;
7205 }
7206
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007207 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007208 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007209 smp->flags = 0;
7210
7211 return 1;
7212}
7213
Emeric Brun2525b6b2012-10-18 15:59:43 +02007214/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007215static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007216smp_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 +02007217{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007218 struct connection *conn;
7219
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007220 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007221 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007222 return 0;
7223
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007224 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007225 smp->flags = SMP_F_MAY_CHANGE;
7226 return 0;
7227 }
7228
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007229 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007230 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007231 smp->flags = 0;
7232
7233 return 1;
7234}
7235
Emeric Brun2525b6b2012-10-18 15:59:43 +02007236/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007237static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007238smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007239{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007240 struct connection *conn;
7241
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007242 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007243 if (!conn || conn->xprt != &ssl_sock)
7244 return 0;
7245
7246 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007247 smp->flags = SMP_F_MAY_CHANGE;
7248 return 0;
7249 }
7250
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007251 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007252 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007253 smp->flags = 0;
7254
7255 return 1;
7256}
7257
Emeric Brun2525b6b2012-10-18 15:59:43 +02007258/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007259static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007260smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007261{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007262 struct connection *conn;
7263
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007264 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007265 if (!conn || conn->xprt != &ssl_sock)
7266 return 0;
7267
7268 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007269 smp->flags = SMP_F_MAY_CHANGE;
7270 return 0;
7271 }
7272
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007273 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007274 return 0;
7275
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007276 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007277 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007278 smp->flags = 0;
7279
7280 return 1;
7281}
7282
Emeric Brunfb510ea2012-10-05 12:00:26 +02007283/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007284static 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 +02007285{
7286 if (!*args[cur_arg + 1]) {
7287 if (err)
7288 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7289 return ERR_ALERT | ERR_FATAL;
7290 }
7291
Willy Tarreauef934602016-12-22 23:12:01 +01007292 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7293 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007294 else
7295 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007296
Emeric Brund94b3fe2012-09-20 18:23:56 +02007297 return 0;
7298}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007299static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7300{
7301 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7302}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007303
Christopher Faulet31af49d2015-06-09 17:29:50 +02007304/* parse the "ca-sign-file" bind keyword */
7305static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7306{
7307 if (!*args[cur_arg + 1]) {
7308 if (err)
7309 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7310 return ERR_ALERT | ERR_FATAL;
7311 }
7312
Willy Tarreauef934602016-12-22 23:12:01 +01007313 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7314 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007315 else
7316 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7317
7318 return 0;
7319}
7320
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007321/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007322static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7323{
7324 if (!*args[cur_arg + 1]) {
7325 if (err)
7326 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7327 return ERR_ALERT | ERR_FATAL;
7328 }
7329 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7330 return 0;
7331}
7332
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007333/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007334static 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 +02007335{
7336 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007337 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007338 return ERR_ALERT | ERR_FATAL;
7339 }
7340
Emeric Brun76d88952012-10-05 15:47:31 +02007341 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007342 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007343 return 0;
7344}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007345static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7346{
7347 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7348}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007349
7350#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7351/* parse the "ciphersuites" bind keyword */
7352static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7353{
7354 if (!*args[cur_arg + 1]) {
7355 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7356 return ERR_ALERT | ERR_FATAL;
7357 }
7358
7359 free(conf->ciphersuites);
7360 conf->ciphersuites = strdup(args[cur_arg + 1]);
7361 return 0;
7362}
7363static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7364{
7365 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7366}
7367#endif
7368
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007369/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007370static 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 +02007371{
Willy Tarreau38011032013-08-13 16:59:39 +02007372 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007373
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007374 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007375 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007376 return ERR_ALERT | ERR_FATAL;
7377 }
7378
Willy Tarreauef934602016-12-22 23:12:01 +01007379 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7380 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007381 memprintf(err, "'%s' : path too long", args[cur_arg]);
7382 return ERR_ALERT | ERR_FATAL;
7383 }
Willy Tarreauef934602016-12-22 23:12:01 +01007384 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007385 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007386 return ERR_ALERT | ERR_FATAL;
7387
7388 return 0;
7389 }
7390
Willy Tarreau03209342016-12-22 17:08:28 +01007391 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007392 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007393
7394 return 0;
7395}
7396
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007397/* parse the "crt-list" bind keyword */
7398static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7399{
7400 if (!*args[cur_arg + 1]) {
7401 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7402 return ERR_ALERT | ERR_FATAL;
7403 }
7404
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007405 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007406 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007407 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007408 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007409
7410 return 0;
7411}
7412
Emeric Brunfb510ea2012-10-05 12:00:26 +02007413/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007414static 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 +02007415{
Emeric Brun051cdab2012-10-02 19:25:50 +02007416#ifndef X509_V_FLAG_CRL_CHECK
7417 if (err)
7418 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7419 return ERR_ALERT | ERR_FATAL;
7420#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007421 if (!*args[cur_arg + 1]) {
7422 if (err)
7423 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7424 return ERR_ALERT | ERR_FATAL;
7425 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007426
Willy Tarreauef934602016-12-22 23:12:01 +01007427 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7428 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007429 else
7430 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007431
Emeric Brun2b58d042012-09-20 17:10:03 +02007432 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007433#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007434}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007435static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7436{
7437 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7438}
Emeric Brun2b58d042012-09-20 17:10:03 +02007439
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007440/* parse the "curves" bind keyword keyword */
7441static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7442{
7443#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7444 if (!*args[cur_arg + 1]) {
7445 if (err)
7446 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7447 return ERR_ALERT | ERR_FATAL;
7448 }
7449 conf->curves = strdup(args[cur_arg + 1]);
7450 return 0;
7451#else
7452 if (err)
7453 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7454 return ERR_ALERT | ERR_FATAL;
7455#endif
7456}
7457static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7458{
7459 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7460}
7461
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007462/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007463static 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 +02007464{
7465#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7466 if (err)
7467 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7468 return ERR_ALERT | ERR_FATAL;
7469#elif defined(OPENSSL_NO_ECDH)
7470 if (err)
7471 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7472 return ERR_ALERT | ERR_FATAL;
7473#else
7474 if (!*args[cur_arg + 1]) {
7475 if (err)
7476 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7477 return ERR_ALERT | ERR_FATAL;
7478 }
7479
7480 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007481
7482 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007483#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007484}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007485static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7486{
7487 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7488}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007489
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007490/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007491static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7492{
7493 int code;
7494 char *p = args[cur_arg + 1];
7495 unsigned long long *ignerr = &conf->crt_ignerr;
7496
7497 if (!*p) {
7498 if (err)
7499 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7500 return ERR_ALERT | ERR_FATAL;
7501 }
7502
7503 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7504 ignerr = &conf->ca_ignerr;
7505
7506 if (strcmp(p, "all") == 0) {
7507 *ignerr = ~0ULL;
7508 return 0;
7509 }
7510
7511 while (p) {
7512 code = atoi(p);
7513 if ((code <= 0) || (code > 63)) {
7514 if (err)
7515 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7516 args[cur_arg], code, args[cur_arg + 1]);
7517 return ERR_ALERT | ERR_FATAL;
7518 }
7519 *ignerr |= 1ULL << code;
7520 p = strchr(p, ',');
7521 if (p)
7522 p++;
7523 }
7524
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007525 return 0;
7526}
7527
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007528/* parse tls_method_options "no-xxx" and "force-xxx" */
7529static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007530{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007531 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007532 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007533 p = strchr(arg, '-');
7534 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007535 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007536 p++;
7537 if (!strcmp(p, "sslv3"))
7538 v = CONF_SSLV3;
7539 else if (!strcmp(p, "tlsv10"))
7540 v = CONF_TLSV10;
7541 else if (!strcmp(p, "tlsv11"))
7542 v = CONF_TLSV11;
7543 else if (!strcmp(p, "tlsv12"))
7544 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007545 else if (!strcmp(p, "tlsv13"))
7546 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007547 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007548 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007549 if (!strncmp(arg, "no-", 3))
7550 methods->flags |= methodVersions[v].flag;
7551 else if (!strncmp(arg, "force-", 6))
7552 methods->min = methods->max = v;
7553 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007554 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007555 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007556 fail:
7557 if (err)
7558 memprintf(err, "'%s' : option not implemented", arg);
7559 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007560}
7561
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007562static 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 +02007563{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007564 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007565}
7566
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007567static 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 +02007568{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007569 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7570}
7571
7572/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7573static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7574{
7575 uint16_t i, v = 0;
7576 char *argv = args[cur_arg + 1];
7577 if (!*argv) {
7578 if (err)
7579 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7580 return ERR_ALERT | ERR_FATAL;
7581 }
7582 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7583 if (!strcmp(argv, methodVersions[i].name))
7584 v = i;
7585 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007586 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007587 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007588 return ERR_ALERT | ERR_FATAL;
7589 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007590 if (!strcmp("ssl-min-ver", args[cur_arg]))
7591 methods->min = v;
7592 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7593 methods->max = v;
7594 else {
7595 if (err)
7596 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7597 return ERR_ALERT | ERR_FATAL;
7598 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007599 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007600}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007601
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007602static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7603{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007604#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007605 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 +02007606#endif
7607 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7608}
7609
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007610static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7611{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007612 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007613}
7614
7615static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7616{
7617 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7618}
7619
Emeric Brun2d0c4822012-10-02 13:45:20 +02007620/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007621static 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 +02007622{
Emeric Brun89675492012-10-05 13:48:26 +02007623 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007624 return 0;
7625}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007626
Olivier Houchardc2aae742017-09-22 18:26:28 +02007627/* parse the "allow-0rtt" bind keyword */
7628static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7629{
7630 conf->early_data = 1;
7631 return 0;
7632}
7633
7634static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7635{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007636 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007637 return 0;
7638}
7639
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007640/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007641static 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 +02007642{
Bernard Spil13c53f82018-02-15 13:34:58 +01007643#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007644 char *p1, *p2;
7645
7646 if (!*args[cur_arg + 1]) {
7647 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7648 return ERR_ALERT | ERR_FATAL;
7649 }
7650
7651 free(conf->npn_str);
7652
Willy Tarreau3724da12016-02-12 17:11:12 +01007653 /* the NPN string is built as a suite of (<len> <name>)*,
7654 * so we reuse each comma to store the next <len> and need
7655 * one more for the end of the string.
7656 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007657 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007658 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007659 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7660
7661 /* replace commas with the name length */
7662 p1 = conf->npn_str;
7663 p2 = p1 + 1;
7664 while (1) {
7665 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7666 if (!p2)
7667 p2 = p1 + 1 + strlen(p1 + 1);
7668
7669 if (p2 - (p1 + 1) > 255) {
7670 *p2 = '\0';
7671 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7672 return ERR_ALERT | ERR_FATAL;
7673 }
7674
7675 *p1 = p2 - (p1 + 1);
7676 p1 = p2;
7677
7678 if (!*p2)
7679 break;
7680
7681 *(p2++) = '\0';
7682 }
7683 return 0;
7684#else
7685 if (err)
7686 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7687 return ERR_ALERT | ERR_FATAL;
7688#endif
7689}
7690
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007691static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7692{
7693 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7694}
7695
Willy Tarreauab861d32013-04-02 02:30:41 +02007696/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007697static 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 +02007698{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007699#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007700 char *p1, *p2;
7701
7702 if (!*args[cur_arg + 1]) {
7703 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7704 return ERR_ALERT | ERR_FATAL;
7705 }
7706
7707 free(conf->alpn_str);
7708
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007709 /* the ALPN string is built as a suite of (<len> <name>)*,
7710 * so we reuse each comma to store the next <len> and need
7711 * one more for the end of the string.
7712 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007713 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007714 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007715 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7716
7717 /* replace commas with the name length */
7718 p1 = conf->alpn_str;
7719 p2 = p1 + 1;
7720 while (1) {
7721 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7722 if (!p2)
7723 p2 = p1 + 1 + strlen(p1 + 1);
7724
7725 if (p2 - (p1 + 1) > 255) {
7726 *p2 = '\0';
7727 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7728 return ERR_ALERT | ERR_FATAL;
7729 }
7730
7731 *p1 = p2 - (p1 + 1);
7732 p1 = p2;
7733
7734 if (!*p2)
7735 break;
7736
7737 *(p2++) = '\0';
7738 }
7739 return 0;
7740#else
7741 if (err)
7742 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7743 return ERR_ALERT | ERR_FATAL;
7744#endif
7745}
7746
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007747static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7748{
7749 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7750}
7751
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007752/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007753static 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 +02007754{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007755 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007756 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007757
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007758 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7759 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007760#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7761 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7762 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7763#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007764 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007765 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7766 if (!conf->ssl_conf.ssl_methods.min)
7767 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7768 if (!conf->ssl_conf.ssl_methods.max)
7769 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007770
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007771 return 0;
7772}
7773
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007774/* parse the "prefer-client-ciphers" bind keyword */
7775static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7776{
7777 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7778 return 0;
7779}
7780
Christopher Faulet31af49d2015-06-09 17:29:50 +02007781/* parse the "generate-certificates" bind keyword */
7782static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7783{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007784#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007785 conf->generate_certs = 1;
7786#else
7787 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7788 err && *err ? *err : "");
7789#endif
7790 return 0;
7791}
7792
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007793/* parse the "strict-sni" bind keyword */
7794static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7795{
7796 conf->strict_sni = 1;
7797 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007798}
7799
7800/* parse the "tls-ticket-keys" bind keyword */
7801static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7802{
7803#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7804 FILE *f;
7805 int i = 0;
7806 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007807 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007808
7809 if (!*args[cur_arg + 1]) {
7810 if (err)
7811 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7812 return ERR_ALERT | ERR_FATAL;
7813 }
7814
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007815 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007816 if (keys_ref) {
7817 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007818 conf->keys_ref = keys_ref;
7819 return 0;
7820 }
7821
Vincent Bernat02779b62016-04-03 13:48:43 +02007822 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007823 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007824
7825 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7826 if (err)
7827 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7828 return ERR_ALERT | ERR_FATAL;
7829 }
7830
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007831 keys_ref->filename = strdup(args[cur_arg + 1]);
7832
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007833 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7834 int len = strlen(thisline);
7835 /* Strip newline characters from the end */
7836 if(thisline[len - 1] == '\n')
7837 thisline[--len] = 0;
7838
7839 if(thisline[len - 1] == '\r')
7840 thisline[--len] = 0;
7841
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007842 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 +01007843 if (err)
7844 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007845 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007846 return ERR_ALERT | ERR_FATAL;
7847 }
7848 i++;
7849 }
7850
7851 if (i < TLS_TICKETS_NO) {
7852 if (err)
7853 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 +02007854 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007855 return ERR_ALERT | ERR_FATAL;
7856 }
7857
7858 fclose(f);
7859
7860 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007861 i -= 2;
7862 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007863 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007864 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007865 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007866 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007867
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007868 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7869
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007870 return 0;
7871#else
7872 if (err)
7873 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7874 return ERR_ALERT | ERR_FATAL;
7875#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007876}
7877
Emeric Brund94b3fe2012-09-20 18:23:56 +02007878/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007879static 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 +02007880{
7881 if (!*args[cur_arg + 1]) {
7882 if (err)
7883 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7884 return ERR_ALERT | ERR_FATAL;
7885 }
7886
7887 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007888 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007889 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007890 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007891 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007892 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007893 else {
7894 if (err)
7895 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7896 args[cur_arg], args[cur_arg + 1]);
7897 return ERR_ALERT | ERR_FATAL;
7898 }
7899
7900 return 0;
7901}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007902static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7903{
7904 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7905}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007906
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007907/* parse the "no-ca-names" bind keyword */
7908static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7909{
7910 conf->no_ca_names = 1;
7911 return 0;
7912}
7913static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7914{
7915 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7916}
7917
Willy Tarreau92faadf2012-10-10 23:04:25 +02007918/************** "server" keywords ****************/
7919
Olivier Houchardc7566002018-11-20 23:33:50 +01007920/* parse the "npn" bind keyword */
7921static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7922{
7923#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7924 char *p1, *p2;
7925
7926 if (!*args[*cur_arg + 1]) {
7927 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7928 return ERR_ALERT | ERR_FATAL;
7929 }
7930
7931 free(newsrv->ssl_ctx.npn_str);
7932
7933 /* the NPN string is built as a suite of (<len> <name>)*,
7934 * so we reuse each comma to store the next <len> and need
7935 * one more for the end of the string.
7936 */
7937 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7938 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7939 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7940 newsrv->ssl_ctx.npn_len);
7941
7942 /* replace commas with the name length */
7943 p1 = newsrv->ssl_ctx.npn_str;
7944 p2 = p1 + 1;
7945 while (1) {
7946 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7947 newsrv->ssl_ctx.npn_len - (p1 + 1));
7948 if (!p2)
7949 p2 = p1 + 1 + strlen(p1 + 1);
7950
7951 if (p2 - (p1 + 1) > 255) {
7952 *p2 = '\0';
7953 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7954 return ERR_ALERT | ERR_FATAL;
7955 }
7956
7957 *p1 = p2 - (p1 + 1);
7958 p1 = p2;
7959
7960 if (!*p2)
7961 break;
7962
7963 *(p2++) = '\0';
7964 }
7965 return 0;
7966#else
7967 if (err)
7968 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7969 return ERR_ALERT | ERR_FATAL;
7970#endif
7971}
7972
Olivier Houchard92150142018-12-21 19:47:01 +01007973/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01007974static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7975{
7976#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7977 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01007978 char **alpn_str;
7979 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01007980
Olivier Houchard92150142018-12-21 19:47:01 +01007981 if (*args[*cur_arg] == 'c') {
7982 alpn_str = &newsrv->check.alpn_str;
7983 alpn_len = &newsrv->check.alpn_len;
7984 } else {
7985 alpn_str = &newsrv->ssl_ctx.alpn_str;
7986 alpn_len = &newsrv->ssl_ctx.alpn_len;
7987
7988 }
Olivier Houchardc7566002018-11-20 23:33:50 +01007989 if (!*args[*cur_arg + 1]) {
7990 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7991 return ERR_ALERT | ERR_FATAL;
7992 }
7993
Olivier Houchard92150142018-12-21 19:47:01 +01007994 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01007995
7996 /* the ALPN string is built as a suite of (<len> <name>)*,
7997 * so we reuse each comma to store the next <len> and need
7998 * one more for the end of the string.
7999 */
Olivier Houchard92150142018-12-21 19:47:01 +01008000 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8001 *alpn_str = calloc(1, *alpn_len + 1);
8002 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008003
8004 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008005 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008006 p2 = p1 + 1;
8007 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008008 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008009 if (!p2)
8010 p2 = p1 + 1 + strlen(p1 + 1);
8011
8012 if (p2 - (p1 + 1) > 255) {
8013 *p2 = '\0';
8014 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8015 return ERR_ALERT | ERR_FATAL;
8016 }
8017
8018 *p1 = p2 - (p1 + 1);
8019 p1 = p2;
8020
8021 if (!*p2)
8022 break;
8023
8024 *(p2++) = '\0';
8025 }
8026 return 0;
8027#else
8028 if (err)
8029 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8030 return ERR_ALERT | ERR_FATAL;
8031#endif
8032}
8033
Emeric Brunef42d922012-10-11 16:11:36 +02008034/* parse the "ca-file" server keyword */
8035static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8036{
8037 if (!*args[*cur_arg + 1]) {
8038 if (err)
8039 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8040 return ERR_ALERT | ERR_FATAL;
8041 }
8042
Willy Tarreauef934602016-12-22 23:12:01 +01008043 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8044 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008045 else
8046 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8047
8048 return 0;
8049}
8050
Olivier Houchard9130a962017-10-17 17:33:43 +02008051/* parse the "check-sni" server keyword */
8052static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8053{
8054 if (!*args[*cur_arg + 1]) {
8055 if (err)
8056 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8057 return ERR_ALERT | ERR_FATAL;
8058 }
8059
8060 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8061 if (!newsrv->check.sni) {
8062 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8063 return ERR_ALERT | ERR_FATAL;
8064 }
8065 return 0;
8066
8067}
8068
Willy Tarreau92faadf2012-10-10 23:04:25 +02008069/* parse the "check-ssl" server keyword */
8070static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8071{
8072 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008073 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8074 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008075#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8076 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8077 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8078#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008079 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008080 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8081 if (!newsrv->ssl_ctx.methods.min)
8082 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8083 if (!newsrv->ssl_ctx.methods.max)
8084 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8085
Willy Tarreau92faadf2012-10-10 23:04:25 +02008086 return 0;
8087}
8088
8089/* parse the "ciphers" server keyword */
8090static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8091{
8092 if (!*args[*cur_arg + 1]) {
8093 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8094 return ERR_ALERT | ERR_FATAL;
8095 }
8096
8097 free(newsrv->ssl_ctx.ciphers);
8098 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8099 return 0;
8100}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008101
8102#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8103/* parse the "ciphersuites" server keyword */
8104static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8105{
8106 if (!*args[*cur_arg + 1]) {
8107 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8108 return ERR_ALERT | ERR_FATAL;
8109 }
8110
8111 free(newsrv->ssl_ctx.ciphersuites);
8112 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8113 return 0;
8114}
8115#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008116
Emeric Brunef42d922012-10-11 16:11:36 +02008117/* parse the "crl-file" server keyword */
8118static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8119{
8120#ifndef X509_V_FLAG_CRL_CHECK
8121 if (err)
8122 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8123 return ERR_ALERT | ERR_FATAL;
8124#else
8125 if (!*args[*cur_arg + 1]) {
8126 if (err)
8127 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8128 return ERR_ALERT | ERR_FATAL;
8129 }
8130
Willy Tarreauef934602016-12-22 23:12:01 +01008131 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8132 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008133 else
8134 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8135
8136 return 0;
8137#endif
8138}
8139
Emeric Bruna7aa3092012-10-26 12:58:00 +02008140/* parse the "crt" server keyword */
8141static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8142{
8143 if (!*args[*cur_arg + 1]) {
8144 if (err)
8145 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8146 return ERR_ALERT | ERR_FATAL;
8147 }
8148
Willy Tarreauef934602016-12-22 23:12:01 +01008149 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008150 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008151 else
8152 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8153
8154 return 0;
8155}
Emeric Brunef42d922012-10-11 16:11:36 +02008156
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008157/* parse the "no-check-ssl" server keyword */
8158static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8159{
8160 newsrv->check.use_ssl = 0;
8161 free(newsrv->ssl_ctx.ciphers);
8162 newsrv->ssl_ctx.ciphers = NULL;
8163 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8164 return 0;
8165}
8166
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008167/* parse the "no-send-proxy-v2-ssl" server keyword */
8168static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8169{
8170 newsrv->pp_opts &= ~SRV_PP_V2;
8171 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8172 return 0;
8173}
8174
8175/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8176static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8177{
8178 newsrv->pp_opts &= ~SRV_PP_V2;
8179 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8180 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8181 return 0;
8182}
8183
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008184/* parse the "no-ssl" server keyword */
8185static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8186{
8187 newsrv->use_ssl = 0;
8188 free(newsrv->ssl_ctx.ciphers);
8189 newsrv->ssl_ctx.ciphers = NULL;
8190 return 0;
8191}
8192
Olivier Houchard522eea72017-11-03 16:27:47 +01008193/* parse the "allow-0rtt" server keyword */
8194static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8195{
8196 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8197 return 0;
8198}
8199
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008200/* parse the "no-ssl-reuse" server keyword */
8201static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8202{
8203 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8204 return 0;
8205}
8206
Emeric Brunf9c5c472012-10-11 15:28:34 +02008207/* parse the "no-tls-tickets" server keyword */
8208static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8209{
8210 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8211 return 0;
8212}
David Safb76832014-05-08 23:42:08 -04008213/* parse the "send-proxy-v2-ssl" server keyword */
8214static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8215{
8216 newsrv->pp_opts |= SRV_PP_V2;
8217 newsrv->pp_opts |= SRV_PP_V2_SSL;
8218 return 0;
8219}
8220
8221/* parse the "send-proxy-v2-ssl-cn" server keyword */
8222static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8223{
8224 newsrv->pp_opts |= SRV_PP_V2;
8225 newsrv->pp_opts |= SRV_PP_V2_SSL;
8226 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8227 return 0;
8228}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008229
Willy Tarreau732eac42015-07-09 11:40:25 +02008230/* parse the "sni" server keyword */
8231static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8232{
8233#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8234 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8235 return ERR_ALERT | ERR_FATAL;
8236#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008237 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008238
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008239 arg = args[*cur_arg + 1];
8240 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008241 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8242 return ERR_ALERT | ERR_FATAL;
8243 }
8244
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008245 free(newsrv->sni_expr);
8246 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008247
Willy Tarreau732eac42015-07-09 11:40:25 +02008248 return 0;
8249#endif
8250}
8251
Willy Tarreau92faadf2012-10-10 23:04:25 +02008252/* parse the "ssl" server keyword */
8253static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8254{
8255 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008256 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8257 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008258#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8259 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8260 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8261#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008262 return 0;
8263}
8264
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008265/* parse the "ssl-reuse" server keyword */
8266static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8267{
8268 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8269 return 0;
8270}
8271
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008272/* parse the "tls-tickets" server keyword */
8273static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8274{
8275 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8276 return 0;
8277}
8278
Emeric Brunef42d922012-10-11 16:11:36 +02008279/* parse the "verify" server keyword */
8280static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8281{
8282 if (!*args[*cur_arg + 1]) {
8283 if (err)
8284 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8285 return ERR_ALERT | ERR_FATAL;
8286 }
8287
8288 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008289 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008290 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008291 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008292 else {
8293 if (err)
8294 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8295 args[*cur_arg], args[*cur_arg + 1]);
8296 return ERR_ALERT | ERR_FATAL;
8297 }
8298
Evan Broderbe554312013-06-27 00:05:25 -07008299 return 0;
8300}
8301
8302/* parse the "verifyhost" server keyword */
8303static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8304{
8305 if (!*args[*cur_arg + 1]) {
8306 if (err)
8307 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8308 return ERR_ALERT | ERR_FATAL;
8309 }
8310
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008311 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008312 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8313
Emeric Brunef42d922012-10-11 16:11:36 +02008314 return 0;
8315}
8316
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008317/* parse the "ssl-default-bind-options" keyword in global section */
8318static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8319 struct proxy *defpx, const char *file, int line,
8320 char **err) {
8321 int i = 1;
8322
8323 if (*(args[i]) == 0) {
8324 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8325 return -1;
8326 }
8327 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008328 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008329 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008330 else if (!strcmp(args[i], "prefer-client-ciphers"))
8331 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008332 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8333 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8334 i++;
8335 else {
8336 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8337 return -1;
8338 }
8339 }
8340 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008341 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8342 return -1;
8343 }
8344 i++;
8345 }
8346 return 0;
8347}
8348
8349/* parse the "ssl-default-server-options" keyword in global section */
8350static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8351 struct proxy *defpx, const char *file, int line,
8352 char **err) {
8353 int i = 1;
8354
8355 if (*(args[i]) == 0) {
8356 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8357 return -1;
8358 }
8359 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008360 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008361 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008362 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8363 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8364 i++;
8365 else {
8366 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8367 return -1;
8368 }
8369 }
8370 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008371 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8372 return -1;
8373 }
8374 i++;
8375 }
8376 return 0;
8377}
8378
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008379/* parse the "ca-base" / "crt-base" keywords in global section.
8380 * Returns <0 on alert, >0 on warning, 0 on success.
8381 */
8382static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8383 struct proxy *defpx, const char *file, int line,
8384 char **err)
8385{
8386 char **target;
8387
Willy Tarreauef934602016-12-22 23:12:01 +01008388 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008389
8390 if (too_many_args(1, args, err, NULL))
8391 return -1;
8392
8393 if (*target) {
8394 memprintf(err, "'%s' already specified.", args[0]);
8395 return -1;
8396 }
8397
8398 if (*(args[1]) == 0) {
8399 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8400 return -1;
8401 }
8402 *target = strdup(args[1]);
8403 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008404}
8405
8406/* parse the "ssl-mode-async" keyword in global section.
8407 * Returns <0 on alert, >0 on warning, 0 on success.
8408 */
8409static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8410 struct proxy *defpx, const char *file, int line,
8411 char **err)
8412{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008413#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008414 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008415 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008416 return 0;
8417#else
8418 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8419 return -1;
8420#endif
8421}
8422
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008423#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008424static int ssl_check_async_engine_count(void) {
8425 int err_code = 0;
8426
Emeric Brun3854e012017-05-17 20:42:48 +02008427 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008428 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008429 err_code = ERR_ABORT;
8430 }
8431 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008432}
8433
Grant Zhang872f9c22017-01-21 01:10:18 +00008434/* parse the "ssl-engine" keyword in global section.
8435 * Returns <0 on alert, >0 on warning, 0 on success.
8436 */
8437static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8438 struct proxy *defpx, const char *file, int line,
8439 char **err)
8440{
8441 char *algo;
8442 int ret = -1;
8443
8444 if (*(args[1]) == 0) {
8445 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8446 return ret;
8447 }
8448
8449 if (*(args[2]) == 0) {
8450 /* if no list of algorithms is given, it defaults to ALL */
8451 algo = strdup("ALL");
8452 goto add_engine;
8453 }
8454
8455 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8456 if (strcmp(args[2], "algo") != 0) {
8457 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8458 return ret;
8459 }
8460
8461 if (*(args[3]) == 0) {
8462 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8463 return ret;
8464 }
8465 algo = strdup(args[3]);
8466
8467add_engine:
8468 if (ssl_init_single_engine(args[1], algo)==0) {
8469 openssl_engines_initialized++;
8470 ret = 0;
8471 }
8472 free(algo);
8473 return ret;
8474}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008475#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008476
Willy Tarreauf22e9682016-12-21 23:23:19 +01008477/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8478 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8479 */
8480static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8481 struct proxy *defpx, const char *file, int line,
8482 char **err)
8483{
8484 char **target;
8485
Willy Tarreauef934602016-12-22 23:12:01 +01008486 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008487
8488 if (too_many_args(1, args, err, NULL))
8489 return -1;
8490
8491 if (*(args[1]) == 0) {
8492 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8493 return -1;
8494 }
8495
8496 free(*target);
8497 *target = strdup(args[1]);
8498 return 0;
8499}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008500
8501#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8502/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8503 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8504 */
8505static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8506 struct proxy *defpx, const char *file, int line,
8507 char **err)
8508{
8509 char **target;
8510
8511 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8512
8513 if (too_many_args(1, args, err, NULL))
8514 return -1;
8515
8516 if (*(args[1]) == 0) {
8517 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8518 return -1;
8519 }
8520
8521 free(*target);
8522 *target = strdup(args[1]);
8523 return 0;
8524}
8525#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008526
Willy Tarreau9ceda382016-12-21 23:13:03 +01008527/* parse various global tune.ssl settings consisting in positive integers.
8528 * Returns <0 on alert, >0 on warning, 0 on success.
8529 */
8530static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8531 struct proxy *defpx, const char *file, int line,
8532 char **err)
8533{
8534 int *target;
8535
8536 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8537 target = &global.tune.sslcachesize;
8538 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008539 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008540 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008541 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008542 else if (strcmp(args[0], "maxsslconn") == 0)
8543 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008544 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8545 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008546 else {
8547 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8548 return -1;
8549 }
8550
8551 if (too_many_args(1, args, err, NULL))
8552 return -1;
8553
8554 if (*(args[1]) == 0) {
8555 memprintf(err, "'%s' expects an integer argument.", args[0]);
8556 return -1;
8557 }
8558
8559 *target = atoi(args[1]);
8560 if (*target < 0) {
8561 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8562 return -1;
8563 }
8564 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008565}
8566
8567static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8568 struct proxy *defpx, const char *file, int line,
8569 char **err)
8570{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008571 int ret;
8572
8573 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8574 if (ret != 0)
8575 return ret;
8576
Willy Tarreaubafbe012017-11-24 17:34:44 +01008577 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008578 memprintf(err, "'%s' is already configured.", args[0]);
8579 return -1;
8580 }
8581
Willy Tarreaubafbe012017-11-24 17:34:44 +01008582 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8583 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008584 memprintf(err, "Out of memory error.");
8585 return -1;
8586 }
8587 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008588}
8589
8590/* parse "ssl.force-private-cache".
8591 * Returns <0 on alert, >0 on warning, 0 on success.
8592 */
8593static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8594 struct proxy *defpx, const char *file, int line,
8595 char **err)
8596{
8597 if (too_many_args(0, args, err, NULL))
8598 return -1;
8599
Willy Tarreauef934602016-12-22 23:12:01 +01008600 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008601 return 0;
8602}
8603
8604/* parse "ssl.lifetime".
8605 * Returns <0 on alert, >0 on warning, 0 on success.
8606 */
8607static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8608 struct proxy *defpx, const char *file, int line,
8609 char **err)
8610{
8611 const char *res;
8612
8613 if (too_many_args(1, args, err, NULL))
8614 return -1;
8615
8616 if (*(args[1]) == 0) {
8617 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8618 return -1;
8619 }
8620
Willy Tarreauef934602016-12-22 23:12:01 +01008621 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008622 if (res) {
8623 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8624 return -1;
8625 }
8626 return 0;
8627}
8628
8629#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008630/* parse "ssl-dh-param-file".
8631 * Returns <0 on alert, >0 on warning, 0 on success.
8632 */
8633static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8634 struct proxy *defpx, const char *file, int line,
8635 char **err)
8636{
8637 if (too_many_args(1, args, err, NULL))
8638 return -1;
8639
8640 if (*(args[1]) == 0) {
8641 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8642 return -1;
8643 }
8644
8645 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8646 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8647 return -1;
8648 }
8649 return 0;
8650}
8651
Willy Tarreau9ceda382016-12-21 23:13:03 +01008652/* parse "ssl.default-dh-param".
8653 * Returns <0 on alert, >0 on warning, 0 on success.
8654 */
8655static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8656 struct proxy *defpx, const char *file, int line,
8657 char **err)
8658{
8659 if (too_many_args(1, args, err, NULL))
8660 return -1;
8661
8662 if (*(args[1]) == 0) {
8663 memprintf(err, "'%s' expects an integer argument.", args[0]);
8664 return -1;
8665 }
8666
Willy Tarreauef934602016-12-22 23:12:01 +01008667 global_ssl.default_dh_param = atoi(args[1]);
8668 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008669 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8670 return -1;
8671 }
8672 return 0;
8673}
8674#endif
8675
8676
William Lallemand32af2032016-10-29 18:09:35 +02008677/* This function is used with TLS ticket keys management. It permits to browse
8678 * each reference. The variable <getnext> must contain the current node,
8679 * <end> point to the root node.
8680 */
8681#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8682static inline
8683struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8684{
8685 struct tls_keys_ref *ref = getnext;
8686
8687 while (1) {
8688
8689 /* Get next list entry. */
8690 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8691
8692 /* If the entry is the last of the list, return NULL. */
8693 if (&ref->list == end)
8694 return NULL;
8695
8696 return ref;
8697 }
8698}
8699
8700static inline
8701struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8702{
8703 int id;
8704 char *error;
8705
8706 /* If the reference starts by a '#', this is numeric id. */
8707 if (reference[0] == '#') {
8708 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8709 id = strtol(reference + 1, &error, 10);
8710 if (*error != '\0')
8711 return NULL;
8712
8713 /* Perform the unique id lookup. */
8714 return tlskeys_ref_lookupid(id);
8715 }
8716
8717 /* Perform the string lookup. */
8718 return tlskeys_ref_lookup(reference);
8719}
8720#endif
8721
8722
8723#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8724
8725static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8726
8727static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8728 return cli_io_handler_tlskeys_files(appctx);
8729}
8730
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008731/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8732 * (next index to be dumped), and cli.p0 (next key reference).
8733 */
William Lallemand32af2032016-10-29 18:09:35 +02008734static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8735
8736 struct stream_interface *si = appctx->owner;
8737
8738 switch (appctx->st2) {
8739 case STAT_ST_INIT:
8740 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008741 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008742 * later and restart at the state "STAT_ST_INIT".
8743 */
8744 chunk_reset(&trash);
8745
8746 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8747 chunk_appendf(&trash, "# id secret\n");
8748 else
8749 chunk_appendf(&trash, "# id (file)\n");
8750
Willy Tarreau06d80a92017-10-19 14:32:15 +02008751 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008752 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008753 return 0;
8754 }
8755
William Lallemand32af2032016-10-29 18:09:35 +02008756 /* Now, we start the browsing of the references lists.
8757 * Note that the following call to LIST_ELEM return bad pointer. The only
8758 * available field of this pointer is <list>. It is used with the function
8759 * tlskeys_list_get_next() for retruning the first available entry
8760 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008761 if (appctx->ctx.cli.p0 == NULL) {
8762 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8763 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008764 }
8765
8766 appctx->st2 = STAT_ST_LIST;
8767 /* fall through */
8768
8769 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008770 while (appctx->ctx.cli.p0) {
8771 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008772
8773 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008774 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008775 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008776
8777 if (appctx->ctx.cli.i1 == 0)
8778 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8779
William Lallemand32af2032016-10-29 18:09:35 +02008780 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008781 int head;
8782
8783 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8784 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008785 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008786 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008787
8788 chunk_reset(t2);
8789 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008790 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8791 sizeof(struct tls_sess_key),
8792 t2->area, t2->size);
8793 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8794 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008795
Willy Tarreau06d80a92017-10-19 14:32:15 +02008796 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008797 /* let's try again later from this stream. We add ourselves into
8798 * this stream's users so that it can remove us upon termination.
8799 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008800 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008801 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008802 return 0;
8803 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008804 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008805 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008806 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008807 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008808 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008809 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008810 /* let's try again later from this stream. We add ourselves into
8811 * this stream's users so that it can remove us upon termination.
8812 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008813 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008814 return 0;
8815 }
8816
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008817 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008818 break;
8819
8820 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008821 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008822 }
8823
8824 appctx->st2 = STAT_ST_FIN;
8825 /* fall through */
8826
8827 default:
8828 appctx->st2 = STAT_ST_FIN;
8829 return 1;
8830 }
8831 return 0;
8832}
8833
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008834/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008835static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008836{
William Lallemand32af2032016-10-29 18:09:35 +02008837 /* no parameter, shows only file list */
8838 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008839 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008840 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008841 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008842 }
8843
8844 if (args[2][0] == '*') {
8845 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008846 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008847 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008848 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8849 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008850 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008851 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008852 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008853 return 1;
8854 }
8855 }
William Lallemand32af2032016-10-29 18:09:35 +02008856 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008857 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008858}
8859
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008860static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008861{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008862 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008863 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008864
William Lallemand32af2032016-10-29 18:09:35 +02008865 /* Expect two parameters: the filename and the new new TLS key in encoding */
8866 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008867 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008868 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 +01008869 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008870 return 1;
8871 }
8872
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008873 ref = tlskeys_ref_lookup_ref(args[3]);
8874 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008875 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008876 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008877 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008878 return 1;
8879 }
8880
Willy Tarreau1c913e42018-08-22 05:26:57 +02008881 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8882 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008883 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008884 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008885 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008886 return 1;
8887 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008888 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008889 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008890 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008891 appctx->ctx.cli.msg = "TLS ticket key updated!\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
8895}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008896#endif
William Lallemand32af2032016-10-29 18:09:35 +02008897
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008898static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008899{
8900#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8901 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008902 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008903
8904 if (!payload)
8905 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008906
8907 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008908 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008909 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008910 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008911 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008912 return 1;
8913 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008914
8915 /* remove \r and \n from the payload */
8916 for (i = 0, j = 0; payload[i]; i++) {
8917 if (payload[i] == '\r' || payload[i] == '\n')
8918 continue;
8919 payload[j++] = payload[i];
8920 }
8921 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008922
Willy Tarreau1c913e42018-08-22 05:26:57 +02008923 ret = base64dec(payload, j, trash.area, trash.size);
8924 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008925 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008926 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008927 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008928 return 1;
8929 }
8930
Willy Tarreau1c913e42018-08-22 05:26:57 +02008931 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008932 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8933 if (err) {
8934 memprintf(&err, "%s.\n", err);
8935 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008936 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008937 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008938 else {
8939 appctx->ctx.cli.severity = LOG_ERR;
8940 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8941 appctx->st0 = CLI_ST_PRINT;
8942 }
William Lallemand32af2032016-10-29 18:09:35 +02008943 return 1;
8944 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008945 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008946 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008947 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008948 return 1;
8949#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008950 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008951 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 +01008952 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008953 return 1;
8954#endif
8955
8956}
8957
8958/* register cli keywords */
8959static struct cli_kw_list cli_kws = {{ },{
8960#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8961 { { "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 +02008962 { { "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 +02008963#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008964 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008965 { { NULL }, NULL, NULL, NULL }
8966}};
8967
Willy Tarreau0108d902018-11-25 19:14:37 +01008968INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008969
Willy Tarreau7875d092012-09-10 08:20:03 +02008970/* Note: must not be declared <const> as its list will be overwritten.
8971 * Please take care of keeping this list alphabetically sorted.
8972 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008973static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008974 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008975 { "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 +01008976#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01008977 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008978#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008979 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008980#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8981 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8982#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008983 { "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 +02008984 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008985 { "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 +02008986 { "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 -04008987#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008988 { "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 -04008989#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008990#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8991 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8992#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008993 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8994 { "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 +01008995 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008996 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008997 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8998 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8999 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9000 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9001 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9002 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9003 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9004 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009005 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009006 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9007 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009008 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009009 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9010 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9011 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9012 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9013 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9014 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9015 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009016 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009017 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009018 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009019 { "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 +01009020 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009021 { "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 +02009022 { "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 +01009023 { "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 +02009024 { "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 +01009025#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009026 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009027#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009028#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009029 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009030#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009031 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009032#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009033 { "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 -04009034#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009035 { "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 -04009036#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009037 { "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 -04009038#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009039#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9040 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9041#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009042#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009043 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009044#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009045 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9046 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9047 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9048 { "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 +02009049 { NULL, NULL, 0, 0, 0 },
9050}};
9051
Willy Tarreau0108d902018-11-25 19:14:37 +01009052INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9053
Willy Tarreau7875d092012-09-10 08:20:03 +02009054/* Note: must not be declared <const> as its list will be overwritten.
9055 * Please take care of keeping this list alphabetically sorted.
9056 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009057static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009058 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9059 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009060 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009061}};
9062
Willy Tarreau0108d902018-11-25 19:14:37 +01009063INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9064
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009065/* Note: must not be declared <const> as its list will be overwritten.
9066 * Please take care of keeping this list alphabetically sorted, doing so helps
9067 * all code contributors.
9068 * Optional keywords are also declared with a NULL ->parse() function so that
9069 * the config parser can report an appropriate error when a known keyword was
9070 * not enabled.
9071 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009072static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009073 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009074 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9075 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9076 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009077#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9078 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9079#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009080 { "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 +01009081 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009082 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009083 { "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 +01009084 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009085 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9086 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009087 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9088 { NULL, NULL, 0 },
9089};
9090
Willy Tarreau0108d902018-11-25 19:14:37 +01009091/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9092
Willy Tarreau51fb7652012-09-18 18:24:39 +02009093static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009094 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009095 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9096 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9097 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9098 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9099 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9100 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009101#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9102 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9103#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009104 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9105 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9106 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9107 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9108 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9109 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9110 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9111 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9112 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9113 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009114 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009115 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009116 { "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 +02009117 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9118 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9119 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9120 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009121 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009122 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9123 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009124 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9125 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009126 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9127 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9128 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9129 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9130 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009131 { NULL, NULL, 0 },
9132}};
Emeric Brun46591952012-05-18 15:47:34 +02009133
Willy Tarreau0108d902018-11-25 19:14:37 +01009134INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9135
Willy Tarreau92faadf2012-10-10 23:04:25 +02009136/* Note: must not be declared <const> as its list will be overwritten.
9137 * Please take care of keeping this list alphabetically sorted, doing so helps
9138 * all code contributors.
9139 * Optional keywords are also declared with a NULL ->parse() function so that
9140 * the config parser can report an appropriate error when a known keyword was
9141 * not enabled.
9142 */
9143static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009144 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009145 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009146 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +01009147 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +02009148 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009149 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9150 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009151#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9152 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9153#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009154 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9155 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9156 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9157 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9158 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9159 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9160 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9161 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9162 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9163 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9164 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9165 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9166 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9167 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9168 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9169 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9170 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9171 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009172 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009173 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9174 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9175 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9176 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9177 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9178 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9179 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9180 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9181 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9182 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009183 { NULL, NULL, 0, 0 },
9184}};
9185
Willy Tarreau0108d902018-11-25 19:14:37 +01009186INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9187
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009188static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009189 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9190 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009191 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009192 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9193 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009194#ifndef OPENSSL_NO_DH
9195 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9196#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009197 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009198#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009199 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009200#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009201 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9202#ifndef OPENSSL_NO_DH
9203 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9204#endif
9205 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9206 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9207 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9208 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009209 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009210 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9211 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009212#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9213 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9214 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9215#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009216 { 0, NULL, NULL },
9217}};
9218
Willy Tarreau0108d902018-11-25 19:14:37 +01009219INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9220
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009221/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009222static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009223 .snd_buf = ssl_sock_from_buf,
9224 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009225 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009226 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009227 .rcv_pipe = NULL,
9228 .snd_pipe = NULL,
9229 .shutr = NULL,
9230 .shutw = ssl_sock_shutw,
9231 .close = ssl_sock_close,
9232 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009233 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009234 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009235 .prepare_srv = ssl_sock_prepare_srv_ctx,
9236 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009237 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009238 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009239};
9240
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009241enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9242 struct session *sess, struct stream *s, int flags)
9243{
9244 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009245 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009246
9247 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009248 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009249
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009250 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009251 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009252 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009253 s->req.flags |= CF_READ_NULL;
9254 return ACT_RET_YIELD;
9255 }
9256 }
9257 return (ACT_RET_CONT);
9258}
9259
9260static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9261{
9262 rule->action_ptr = ssl_action_wait_for_hs;
9263
9264 return ACT_RET_PRS_OK;
9265}
9266
9267static struct action_kw_list http_req_actions = {ILH, {
9268 { "wait-for-handshake", ssl_parse_wait_for_hs },
9269 { /* END */ }
9270}};
9271
Willy Tarreau0108d902018-11-25 19:14:37 +01009272INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9273
Daniel Jakots54ffb912015-11-06 20:02:41 +01009274#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009275
9276static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9277{
9278 if (ptr) {
9279 chunk_destroy(ptr);
9280 free(ptr);
9281 }
9282}
9283
9284#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009285static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9286{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009287 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009288}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009289
Emeric Brun46591952012-05-18 15:47:34 +02009290__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009291static void __ssl_sock_init(void)
9292{
Emeric Brun46591952012-05-18 15:47:34 +02009293 STACK_OF(SSL_COMP)* cm;
9294
Willy Tarreauef934602016-12-22 23:12:01 +01009295 if (global_ssl.listen_default_ciphers)
9296 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9297 if (global_ssl.connect_default_ciphers)
9298 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009299#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9300 if (global_ssl.listen_default_ciphersuites)
9301 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9302 if (global_ssl.connect_default_ciphersuites)
9303 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9304#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009305
Willy Tarreau13e14102016-12-22 20:25:26 +01009306 xprt_register(XPRT_SSL, &ssl_sock);
Rosen Penev68185952018-12-14 08:47:02 -08009307#if OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +02009308 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -08009309#endif
Emeric Brun46591952012-05-18 15:47:34 +02009310 cm = SSL_COMP_get_compression_methods();
9311 sk_SSL_COMP_zero(cm);
Rosen Penev68185952018-12-14 08:47:02 -08009312#if defined(USE_THREAD) && ((OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER))
Emeric Brun821bb9b2017-06-15 16:37:39 +02009313 ssl_locking_init();
9314#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009315#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009316 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9317#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009318 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009319 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 +01009320 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009321#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009322 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009323 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009324#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009325#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9326 hap_register_post_check(tlskeys_finalize_config);
9327#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009328
9329 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9330 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9331
9332#ifndef OPENSSL_NO_DH
9333 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9334 hap_register_post_deinit(ssl_free_dh);
9335#endif
9336#ifndef OPENSSL_NO_ENGINE
9337 hap_register_post_deinit(ssl_free_engines);
9338#endif
9339 /* Load SSL string for the verbose & debug mode. */
9340 ERR_load_SSL_strings();
9341}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009342
Willy Tarreau80713382018-11-26 10:19:54 +01009343/* Compute and register the version string */
9344static void ssl_register_build_options()
9345{
9346 char *ptr = NULL;
9347 int i;
9348
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009349 memprintf(&ptr, "Built with OpenSSL version : "
9350#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009351 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009352#else /* OPENSSL_IS_BORINGSSL */
9353 OPENSSL_VERSION_TEXT
9354 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -08009355 OpenSSL_version(OPENSSL_VERSION),
9356 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009357#endif
9358 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9359#if OPENSSL_VERSION_NUMBER < 0x00907000L
9360 "no (library version too old)"
9361#elif defined(OPENSSL_NO_TLSEXT)
9362 "no (disabled via OPENSSL_NO_TLSEXT)"
9363#else
9364 "yes"
9365#endif
9366 "", ptr);
9367
9368 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9369#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9370 "yes"
9371#else
9372#ifdef OPENSSL_NO_TLSEXT
9373 "no (because of OPENSSL_NO_TLSEXT)"
9374#else
9375 "no (version might be too old, 0.9.8f min needed)"
9376#endif
9377#endif
9378 "", ptr);
9379
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009380 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9381 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9382 if (methodVersions[i].option)
9383 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009384
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009385 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009386}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009387
Willy Tarreau80713382018-11-26 10:19:54 +01009388INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009389
Emeric Brun46591952012-05-18 15:47:34 +02009390
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009391#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009392void ssl_free_engines(void) {
9393 struct ssl_engine_list *wl, *wlb;
9394 /* free up engine list */
9395 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9396 ENGINE_finish(wl->e);
9397 ENGINE_free(wl->e);
9398 LIST_DEL(&wl->list);
9399 free(wl);
9400 }
9401}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009402#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009403
Remi Gacogned3a23c32015-05-28 16:39:47 +02009404#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009405void ssl_free_dh(void) {
9406 if (local_dh_1024) {
9407 DH_free(local_dh_1024);
9408 local_dh_1024 = NULL;
9409 }
9410 if (local_dh_2048) {
9411 DH_free(local_dh_2048);
9412 local_dh_2048 = NULL;
9413 }
9414 if (local_dh_4096) {
9415 DH_free(local_dh_4096);
9416 local_dh_4096 = NULL;
9417 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009418 if (global_dh) {
9419 DH_free(global_dh);
9420 global_dh = NULL;
9421 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009422}
9423#endif
9424
9425__attribute__((destructor))
9426static void __ssl_sock_deinit(void)
9427{
9428#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009429 if (ssl_ctx_lru_tree) {
9430 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009431 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009432 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009433#endif
9434
Rosen Penev68185952018-12-14 08:47:02 -08009435#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009436 ERR_remove_state(0);
9437 ERR_free_strings();
9438
9439 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -08009440#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +02009441
Rosen Penev68185952018-12-14 08:47:02 -08009442#if ((OPENSSL_VERSION_NUMBER >= 0x00907000L) && (OPENSSL_VERSION_NUMBER < 0x10100000L)) || defined(LIBRESSL_VERSION_NUMBER)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009443 CRYPTO_cleanup_all_ex_data();
9444#endif
9445}
9446
9447
Emeric Brun46591952012-05-18 15:47:34 +02009448/*
9449 * Local variables:
9450 * c-indent-level: 8
9451 * c-basic-offset: 8
9452 * End:
9453 */