blob: 3e54e011bbb5c6f5a3e3282317a9b040ca59fe3a [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020046#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010047#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020048#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000056#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020057#endif
Emeric Brun46591952012-05-18 15:47:34 +020058
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020059#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000060#include <openssl/async.h>
61#endif
62
Christopher Faulet31af49d2015-06-09 17:29:50 +020063#include <import/lru.h>
64#include <import/xxhash.h>
65
Emeric Brun46591952012-05-18 15:47:34 +020066#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020067#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020068#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020094#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020095#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020096#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010097#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020098#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020099#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +0200100#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200101#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200102#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200103#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200104#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200105#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200106#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200107#include <proto/task.h>
108
Willy Tarreau518cedd2014-02-17 15:43:01 +0100109/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200110#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100111#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100112#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200113#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
114
Emeric Brunf282a812012-09-21 15:27:54 +0200115/* bits 0xFFFF0000 are reserved to store verify errors */
116
117/* Verify errors macros */
118#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
119#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
120#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
121
122#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
123#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
124#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200125
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100126/* Supported hash function for TLS tickets */
127#ifdef OPENSSL_NO_SHA256
128#define HASH_FUNCT EVP_sha1
129#else
130#define HASH_FUNCT EVP_sha256
131#endif /* OPENSSL_NO_SHA256 */
132
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200133/* ssl_methods flags for ssl options */
134#define MC_SSL_O_ALL 0x0000
135#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
136#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
137#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
138#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200139#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200140
141/* ssl_methods versions */
142enum {
143 CONF_TLSV_NONE = 0,
144 CONF_TLSV_MIN = 1,
145 CONF_SSLV3 = 1,
146 CONF_TLSV10 = 2,
147 CONF_TLSV11 = 3,
148 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200149 CONF_TLSV13 = 5,
150 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200151};
152
Emeric Brun850efd52014-01-29 12:24:34 +0100153/* server and bind verify method, it uses a global value as default */
154enum {
155 SSL_SOCK_VERIFY_DEFAULT = 0,
156 SSL_SOCK_VERIFY_REQUIRED = 1,
157 SSL_SOCK_VERIFY_OPTIONAL = 2,
158 SSL_SOCK_VERIFY_NONE = 3,
159};
160
William Lallemand3f85c9a2017-10-09 16:30:50 +0200161
Willy Tarreau71b734c2014-01-28 15:19:44 +0100162int sslconns = 0;
163int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100164static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100165int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200166
Willy Tarreauef934602016-12-22 23:12:01 +0100167static struct {
168 char *crt_base; /* base directory path for certificates */
169 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000170 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100171
172 char *listen_default_ciphers;
173 char *connect_default_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200174#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
175 char *listen_default_ciphersuites;
176 char *connect_default_ciphersuites;
177#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100178 int listen_default_ssloptions;
179 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200180 struct tls_version_filter listen_default_sslmethods;
181 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100182
183 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
184 unsigned int life_time; /* SSL session lifetime in seconds */
185 unsigned int max_record; /* SSL max record size */
186 unsigned int default_dh_param; /* SSL maximum DH parameter size */
187 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100188 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100189} global_ssl = {
190#ifdef LISTEN_DEFAULT_CIPHERS
191 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
192#endif
193#ifdef CONNECT_DEFAULT_CIPHERS
194 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
195#endif
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200196#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
197#ifdef LISTEN_DEFAULT_CIPHERSUITES
198 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
199#endif
200#ifdef CONNECT_DEFAULT_CIPHERSUITES
201 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
202#endif
203#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100204 .listen_default_ssloptions = BC_SSL_O_NONE,
205 .connect_default_ssloptions = SRV_SSL_O_NONE,
206
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200207 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
208 .listen_default_sslmethods.min = CONF_TLSV_NONE,
209 .listen_default_sslmethods.max = CONF_TLSV_NONE,
210 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
211 .connect_default_sslmethods.min = CONF_TLSV_NONE,
212 .connect_default_sslmethods.max = CONF_TLSV_NONE,
213
Willy Tarreauef934602016-12-22 23:12:01 +0100214#ifdef DEFAULT_SSL_MAX_RECORD
215 .max_record = DEFAULT_SSL_MAX_RECORD,
216#endif
217 .default_dh_param = SSL_DEFAULT_DH_PARAM,
218 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100219 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100220};
221
Emeric Brun821bb9b2017-06-15 16:37:39 +0200222#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100223
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224static HA_RWLOCK_T *ssl_rwlocks;
225
226
227unsigned long ssl_id_function(void)
228{
229 return (unsigned long)tid;
230}
231
232void ssl_locking_function(int mode, int n, const char * file, int line)
233{
234 if (mode & CRYPTO_LOCK) {
235 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100236 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200237 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100238 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200239 }
240 else {
241 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100242 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200243 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245 }
246}
247
248static int ssl_locking_init(void)
249{
250 int i;
251
252 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
253 if (!ssl_rwlocks)
254 return -1;
255
256 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100257 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200258
259 CRYPTO_set_id_callback(ssl_id_function);
260 CRYPTO_set_locking_callback(ssl_locking_function);
261
262 return 0;
263}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100264
Emeric Brun821bb9b2017-06-15 16:37:39 +0200265#endif
266
267
268
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100269/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100270struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100271 unsigned long long int xxh64;
272 unsigned char ciphersuite_len;
273 char ciphersuite[0];
274};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100275struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100276static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200277static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100278
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100279static int ssl_pkey_info_index = -1;
280
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200281#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
282struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
283#endif
284
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200285#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000286static unsigned int openssl_engines_initialized;
287struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
288struct ssl_engine_list {
289 struct list list;
290 ENGINE *e;
291};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200292#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000293
Remi Gacogne8de54152014-07-15 11:36:40 +0200294#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200295static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200296static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200297static DH *local_dh_1024 = NULL;
298static DH *local_dh_2048 = NULL;
299static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100300static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200301#endif /* OPENSSL_NO_DH */
302
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100303#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200304/* X509V3 Extensions that will be added on generated certificates */
305#define X509V3_EXT_SIZE 5
306static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
307 "basicConstraints",
308 "nsComment",
309 "subjectKeyIdentifier",
310 "authorityKeyIdentifier",
311 "keyUsage",
312};
313static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
314 "CA:FALSE",
315 "\"OpenSSL Generated Certificate\"",
316 "hash",
317 "keyid,issuer:always",
318 "nonRepudiation,digitalSignature,keyEncipherment"
319};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200320/* LRU cache to store generated certificate */
321static struct lru64_head *ssl_ctx_lru_tree = NULL;
322static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200323static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100324__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200325
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200326#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
327
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100328static struct ssl_bind_kw ssl_bind_kws[];
329
yanbzhube2774d2015-12-10 15:07:30 -0500330#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
331/* The order here matters for picking a default context,
332 * keep the most common keytype at the bottom of the list
333 */
334const char *SSL_SOCK_KEYTYPE_NAMES[] = {
335 "dsa",
336 "ecdsa",
337 "rsa"
338};
339#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100340#else
341#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500342#endif
343
William Lallemandc3cd35f2017-11-28 11:04:43 +0100344static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100345static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
346
347#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
348
349#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
350 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
351
352#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
353 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200354
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100355/*
356 * This function gives the detail of the SSL error. It is used only
357 * if the debug mode and the verbose mode are activated. It dump all
358 * the SSL error until the stack was empty.
359 */
360static forceinline void ssl_sock_dump_errors(struct connection *conn)
361{
362 unsigned long ret;
363
364 if (unlikely(global.mode & MODE_DEBUG)) {
365 while(1) {
366 ret = ERR_get_error();
367 if (ret == 0)
368 return;
369 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200370 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100371 ERR_func_error_string(ret), ERR_reason_error_string(ret));
372 }
373 }
374}
375
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200376#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500377/*
378 * struct alignment works here such that the key.key is the same as key_data
379 * Do not change the placement of key_data
380 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200381struct certificate_ocsp {
382 struct ebmb_node key;
383 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200384 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200385 long expire;
386};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200387
yanbzhube2774d2015-12-10 15:07:30 -0500388struct ocsp_cbk_arg {
389 int is_single;
390 int single_kt;
391 union {
392 struct certificate_ocsp *s_ocsp;
393 /*
394 * m_ocsp will have multiple entries dependent on key type
395 * Entry 0 - DSA
396 * Entry 1 - ECDSA
397 * Entry 2 - RSA
398 */
399 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
400 };
401};
402
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200403#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000404static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
405{
406 int err_code = ERR_ABORT;
407 ENGINE *engine;
408 struct ssl_engine_list *el;
409
410 /* grab the structural reference to the engine */
411 engine = ENGINE_by_id(engine_id);
412 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100413 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000414 goto fail_get;
415 }
416
417 if (!ENGINE_init(engine)) {
418 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100419 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000420 goto fail_init;
421 }
422
423 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100424 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000425 goto fail_set_method;
426 }
427
428 el = calloc(1, sizeof(*el));
429 el->e = engine;
430 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100431 nb_engines++;
432 if (global_ssl.async)
433 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000434 return 0;
435
436fail_set_method:
437 /* release the functional reference from ENGINE_init() */
438 ENGINE_finish(engine);
439
440fail_init:
441 /* release the structural reference from ENGINE_by_id() */
442 ENGINE_free(engine);
443
444fail_get:
445 return err_code;
446}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200447#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000448
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200449#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200450/*
451 * openssl async fd handler
452 */
453static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000454{
455 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456
Emeric Brun3854e012017-05-17 20:42:48 +0200457 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000458 * to poll this fd until it is requested
459 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000460 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000461 fd_cant_recv(fd);
462
463 /* crypto engine is available, let's notify the associated
464 * connection that it can pursue its processing.
465 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000466 __conn_sock_want_recv(conn);
467 __conn_sock_want_send(conn);
468 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000469}
470
Emeric Brun3854e012017-05-17 20:42:48 +0200471/*
472 * openssl async delayed SSL_free handler
473 */
474static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000475{
476 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200477 OSSL_ASYNC_FD all_fd[32];
478 size_t num_all_fds = 0;
479 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000480
Emeric Brun3854e012017-05-17 20:42:48 +0200481 /* We suppose that the async job for a same SSL *
482 * are serialized. So if we are awake it is
483 * because the running job has just finished
484 * and we can remove all async fds safely
485 */
486 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
487 if (num_all_fds > 32) {
488 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
489 return;
490 }
491
492 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
493 for (i=0 ; i < num_all_fds ; i++)
494 fd_remove(all_fd[i]);
495
496 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000497 SSL_free(ssl);
Emeric Brun7ad43e72018-10-10 14:51:02 +0200498 HA_ATOMIC_SUB(&sslconns, 1);
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200499 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000500}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501/*
Emeric Brun3854e012017-05-17 20:42:48 +0200502 * function used to manage a returned SSL_ERROR_WANT_ASYNC
503 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000504 */
Emeric Brun3854e012017-05-17 20:42:48 +0200505static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000506{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100507 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200508 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000509 size_t num_add_fds = 0;
510 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200511 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000512
513 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
514 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200515 if (num_add_fds > 32 || num_del_fds > 32) {
516 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517 return;
518 }
519
Emeric Brun3854e012017-05-17 20:42:48 +0200520 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521
Emeric Brun3854e012017-05-17 20:42:48 +0200522 /* We remove unused fds from the fdtab */
523 for (i=0 ; i < num_del_fds ; i++)
524 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000525
Emeric Brun3854e012017-05-17 20:42:48 +0200526 /* We add new fds to the fdtab */
527 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100528 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000529 }
530
Emeric Brun3854e012017-05-17 20:42:48 +0200531 num_add_fds = 0;
532 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
533 if (num_add_fds > 32) {
534 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
535 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536 }
Emeric Brun3854e012017-05-17 20:42:48 +0200537
538 /* We activate the polling for all known async fds */
539 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000540 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200541 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000542 /* To ensure that the fd cache won't be used
543 * We'll prefer to catch a real RD event
544 * because handling an EAGAIN on this fd will
545 * result in a context switch and also
546 * some engines uses a fd in blocking mode.
547 */
548 fd_cant_recv(add_fd[i]);
549 }
Emeric Brun3854e012017-05-17 20:42:48 +0200550
551 /* We must also prevent the conn_handler
552 * to be called until a read event was
553 * polled on an async fd
554 */
555 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000556}
557#endif
558
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200559/*
560 * This function returns the number of seconds elapsed
561 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
562 * date presented un ASN1_GENERALIZEDTIME.
563 *
564 * In parsing error case, it returns -1.
565 */
566static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
567{
568 long epoch;
569 char *p, *end;
570 const unsigned short month_offset[12] = {
571 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
572 };
573 int year, month;
574
575 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
576
577 p = (char *)d->data;
578 end = p + d->length;
579
580 if (end - p < 4) return -1;
581 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
582 p += 4;
583 if (end - p < 2) return -1;
584 month = 10 * (p[0] - '0') + p[1] - '0';
585 if (month < 1 || month > 12) return -1;
586 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
587 We consider leap years and the current month (<marsh or not) */
588 epoch = ( ((year - 1970) * 365)
589 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
590 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
591 + month_offset[month-1]
592 ) * 24 * 60 * 60;
593 p += 2;
594 if (end - p < 2) return -1;
595 /* Add the number of seconds of completed days of current month */
596 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
597 p += 2;
598 if (end - p < 2) return -1;
599 /* Add the completed hours of the current day */
600 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
601 p += 2;
602 if (end - p < 2) return -1;
603 /* Add the completed minutes of the current hour */
604 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
605 p += 2;
606 if (p == end) return -1;
607 /* Test if there is available seconds */
608 if (p[0] < '0' || p[0] > '9')
609 goto nosec;
610 if (end - p < 2) return -1;
611 /* Add the seconds of the current minute */
612 epoch += 10 * (p[0] - '0') + p[1] - '0';
613 p += 2;
614 if (p == end) return -1;
615 /* Ignore seconds float part if present */
616 if (p[0] == '.') {
617 do {
618 if (++p == end) return -1;
619 } while (p[0] >= '0' && p[0] <= '9');
620 }
621
622nosec:
623 if (p[0] == 'Z') {
624 if (end - p != 1) return -1;
625 return epoch;
626 }
627 else if (p[0] == '+') {
628 if (end - p != 5) return -1;
629 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700630 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200631 }
632 else if (p[0] == '-') {
633 if (end - p != 5) return -1;
634 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700635 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200636 }
637
638 return -1;
639}
640
Emeric Brun1d3865b2014-06-20 15:37:32 +0200641static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200642
643/* This function starts to check if the OCSP response (in DER format) contained
644 * in chunk 'ocsp_response' is valid (else exits on error).
645 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
646 * contained in the OCSP Response and exits on error if no match.
647 * If it's a valid OCSP Response:
648 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
649 * pointed by 'ocsp'.
650 * If 'ocsp' is NULL, the function looks up into the OCSP response's
651 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
652 * from the response) and exits on error if not found. Finally, If an OCSP response is
653 * already present in the container, it will be overwritten.
654 *
655 * Note: OCSP response containing more than one OCSP Single response is not
656 * considered valid.
657 *
658 * Returns 0 on success, 1 in error case.
659 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200660static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
661 struct certificate_ocsp *ocsp,
662 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200663{
664 OCSP_RESPONSE *resp;
665 OCSP_BASICRESP *bs = NULL;
666 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200667 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200668 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200669 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200670 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200671 int reason;
672 int ret = 1;
673
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200674 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
675 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200676 if (!resp) {
677 memprintf(err, "Unable to parse OCSP response");
678 goto out;
679 }
680
681 rc = OCSP_response_status(resp);
682 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
683 memprintf(err, "OCSP response status not successful");
684 goto out;
685 }
686
687 bs = OCSP_response_get1_basic(resp);
688 if (!bs) {
689 memprintf(err, "Failed to get basic response from OCSP Response");
690 goto out;
691 }
692
693 count_sr = OCSP_resp_count(bs);
694 if (count_sr > 1) {
695 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
696 goto out;
697 }
698
699 sr = OCSP_resp_get0(bs, 0);
700 if (!sr) {
701 memprintf(err, "Failed to get OCSP single response");
702 goto out;
703 }
704
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200705 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
706
Emeric Brun4147b2e2014-06-16 18:36:30 +0200707 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200708 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200709 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200710 goto out;
711 }
712
Emeric Brun13a6b482014-06-20 15:44:34 +0200713 if (!nextupd) {
714 memprintf(err, "OCSP single response: missing nextupdate");
715 goto out;
716 }
717
Emeric Brunc8b27b62014-06-19 14:16:17 +0200718 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200719 if (!rc) {
720 memprintf(err, "OCSP single response: no longer valid.");
721 goto out;
722 }
723
724 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200725 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200726 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
727 goto out;
728 }
729 }
730
731 if (!ocsp) {
732 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
733 unsigned char *p;
734
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200735 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200736 if (!rc) {
737 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
738 goto out;
739 }
740
741 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
742 memprintf(err, "OCSP single response: Certificate ID too long");
743 goto out;
744 }
745
746 p = key;
747 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200748 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200749 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
750 if (!ocsp) {
751 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
752 goto out;
753 }
754 }
755
756 /* According to comments on "chunk_dup", the
757 previous chunk buffer will be freed */
758 if (!chunk_dup(&ocsp->response, ocsp_response)) {
759 memprintf(err, "OCSP response: Memory allocation error");
760 goto out;
761 }
762
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200763 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
764
Emeric Brun4147b2e2014-06-16 18:36:30 +0200765 ret = 0;
766out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100767 ERR_clear_error();
768
Emeric Brun4147b2e2014-06-16 18:36:30 +0200769 if (bs)
770 OCSP_BASICRESP_free(bs);
771
772 if (resp)
773 OCSP_RESPONSE_free(resp);
774
775 return ret;
776}
777/*
778 * External function use to update the OCSP response in the OCSP response's
779 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
780 * to update in DER format.
781 *
782 * Returns 0 on success, 1 in error case.
783 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200784int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200785{
786 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
787}
788
789/*
790 * This function load the OCSP Resonse in DER format contained in file at
791 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
792 *
793 * Returns 0 on success, 1 in error case.
794 */
795static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
796{
797 int fd = -1;
798 int r = 0;
799 int ret = 1;
800
801 fd = open(ocsp_path, O_RDONLY);
802 if (fd == -1) {
803 memprintf(err, "Error opening OCSP response file");
804 goto end;
805 }
806
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200807 trash.data = 0;
808 while (trash.data < trash.size) {
809 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200810 if (r < 0) {
811 if (errno == EINTR)
812 continue;
813
814 memprintf(err, "Error reading OCSP response from file");
815 goto end;
816 }
817 else if (r == 0) {
818 break;
819 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200820 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200821 }
822
823 close(fd);
824 fd = -1;
825
826 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
827end:
828 if (fd != -1)
829 close(fd);
830
831 return ret;
832}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100833#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200834
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100835#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
836static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
837{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100838 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100839 struct tls_sess_key *keys;
840 struct connection *conn;
841 int head;
842 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100843 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100844
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200845 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200846 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100847 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
848
849 keys = ref->tlskeys;
850 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100851
852 if (enc) {
853 memcpy(key_name, keys[head].name, 16);
854
855 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100856 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857
858 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100859 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100860
861 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100862 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100863 } else {
864 for (i = 0; i < TLS_TICKETS_NO; i++) {
865 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
866 goto found;
867 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100868 ret = 0;
869 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100870
Christopher Faulet16f45c82018-02-16 11:23:49 +0100871 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100872 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
873 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100874 goto end;
875
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100876 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100877 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100878 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100879 end:
880 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
881 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200882}
883
884struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
885{
886 struct tls_keys_ref *ref;
887
888 list_for_each_entry(ref, &tlskeys_reference, list)
889 if (ref->filename && strcmp(filename, ref->filename) == 0)
890 return ref;
891 return NULL;
892}
893
894struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
895{
896 struct tls_keys_ref *ref;
897
898 list_for_each_entry(ref, &tlskeys_reference, list)
899 if (ref->unique_id == unique_id)
900 return ref;
901 return NULL;
902}
903
Willy Tarreau83061a82018-07-13 11:56:34 +0200904void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
905 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100906{
907 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200908 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
909 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100910 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
911 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
912}
913
Willy Tarreau83061a82018-07-13 11:56:34 +0200914int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100915{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200916 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
917
918 if(!ref) {
919 memprintf(err, "Unable to locate the referenced filename: %s", filename);
920 return 1;
921 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100922 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200923 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100924}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200925
926/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100927 * automatic ids. It's called just after the basic checks. It returns
928 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200929 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100930static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200931{
932 int i = 0;
933 struct tls_keys_ref *ref, *ref2, *ref3;
934 struct list tkr = LIST_HEAD_INIT(tkr);
935
936 list_for_each_entry(ref, &tlskeys_reference, list) {
937 if (ref->unique_id == -1) {
938 /* Look for the first free id. */
939 while (1) {
940 list_for_each_entry(ref2, &tlskeys_reference, list) {
941 if (ref2->unique_id == i) {
942 i++;
943 break;
944 }
945 }
946 if (&ref2->list == &tlskeys_reference)
947 break;
948 }
949
950 /* Uses the unique id and increment it for the next entry. */
951 ref->unique_id = i;
952 i++;
953 }
954 }
955
956 /* This sort the reference list by id. */
957 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
958 LIST_DEL(&ref->list);
959 list_for_each_entry(ref3, &tkr, list) {
960 if (ref->unique_id < ref3->unique_id) {
961 LIST_ADDQ(&ref3->list, &ref->list);
962 break;
963 }
964 }
965 if (&ref3->list == &tkr)
966 LIST_ADDQ(&tkr, &ref->list);
967 }
968
969 /* swap root */
970 LIST_ADD(&tkr, &tlskeys_reference);
971 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100972 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200973}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100974#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
975
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100976#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500977int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
978{
979 switch (evp_keytype) {
980 case EVP_PKEY_RSA:
981 return 2;
982 case EVP_PKEY_DSA:
983 return 0;
984 case EVP_PKEY_EC:
985 return 1;
986 }
987
988 return -1;
989}
990
Emeric Brun4147b2e2014-06-16 18:36:30 +0200991/*
992 * Callback used to set OCSP status extension content in server hello.
993 */
994int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
995{
yanbzhube2774d2015-12-10 15:07:30 -0500996 struct certificate_ocsp *ocsp;
997 struct ocsp_cbk_arg *ocsp_arg;
998 char *ssl_buf;
999 EVP_PKEY *ssl_pkey;
1000 int key_type;
1001 int index;
1002
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001003 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001004
1005 ssl_pkey = SSL_get_privatekey(ssl);
1006 if (!ssl_pkey)
1007 return SSL_TLSEXT_ERR_NOACK;
1008
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001009 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001010
1011 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1012 ocsp = ocsp_arg->s_ocsp;
1013 else {
1014 /* For multiple certs per context, we have to find the correct OCSP response based on
1015 * the certificate type
1016 */
1017 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1018
1019 if (index < 0)
1020 return SSL_TLSEXT_ERR_NOACK;
1021
1022 ocsp = ocsp_arg->m_ocsp[index];
1023
1024 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001025
1026 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001027 !ocsp->response.area ||
1028 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001029 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001030 return SSL_TLSEXT_ERR_NOACK;
1031
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001032 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001033 if (!ssl_buf)
1034 return SSL_TLSEXT_ERR_NOACK;
1035
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001036 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1037 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001038
1039 return SSL_TLSEXT_ERR_OK;
1040}
1041
1042/*
1043 * This function enables the handling of OCSP status extension on 'ctx' if a
1044 * file name 'cert_path' suffixed using ".ocsp" is present.
1045 * To enable OCSP status extension, the issuer's certificate is mandatory.
1046 * It should be present in the certificate's extra chain builded from file
1047 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1048 * named 'cert_path' suffixed using '.issuer'.
1049 *
1050 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1051 * response. If file is empty or content is not a valid OCSP response,
1052 * OCSP status extension is enabled but OCSP response is ignored (a warning
1053 * is displayed).
1054 *
1055 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001056 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001057 */
1058static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1059{
1060
1061 BIO *in = NULL;
1062 X509 *x, *xi = NULL, *issuer = NULL;
1063 STACK_OF(X509) *chain = NULL;
1064 OCSP_CERTID *cid = NULL;
1065 SSL *ssl;
1066 char ocsp_path[MAXPATHLEN+1];
1067 int i, ret = -1;
1068 struct stat st;
1069 struct certificate_ocsp *ocsp = NULL, *iocsp;
1070 char *warn = NULL;
1071 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001072 pem_password_cb *passwd_cb;
1073 void *passwd_cb_userdata;
1074 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001075
1076 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1077
1078 if (stat(ocsp_path, &st))
1079 return 1;
1080
1081 ssl = SSL_new(ctx);
1082 if (!ssl)
1083 goto out;
1084
1085 x = SSL_get_certificate(ssl);
1086 if (!x)
1087 goto out;
1088
1089 /* Try to lookup for issuer in certificate extra chain */
1090#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1091 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1092#else
1093 chain = ctx->extra_certs;
1094#endif
1095 for (i = 0; i < sk_X509_num(chain); i++) {
1096 issuer = sk_X509_value(chain, i);
1097 if (X509_check_issued(issuer, x) == X509_V_OK)
1098 break;
1099 else
1100 issuer = NULL;
1101 }
1102
1103 /* If not found try to load issuer from a suffixed file */
1104 if (!issuer) {
1105 char issuer_path[MAXPATHLEN+1];
1106
1107 in = BIO_new(BIO_s_file());
1108 if (!in)
1109 goto out;
1110
1111 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1112 if (BIO_read_filename(in, issuer_path) <= 0)
1113 goto out;
1114
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001115 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1116 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1117
1118 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001119 if (!xi)
1120 goto out;
1121
1122 if (X509_check_issued(xi, x) != X509_V_OK)
1123 goto out;
1124
1125 issuer = xi;
1126 }
1127
1128 cid = OCSP_cert_to_id(0, x, issuer);
1129 if (!cid)
1130 goto out;
1131
1132 i = i2d_OCSP_CERTID(cid, NULL);
1133 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1134 goto out;
1135
Vincent Bernat02779b62016-04-03 13:48:43 +02001136 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001137 if (!ocsp)
1138 goto out;
1139
1140 p = ocsp->key_data;
1141 i2d_OCSP_CERTID(cid, &p);
1142
1143 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1144 if (iocsp == ocsp)
1145 ocsp = NULL;
1146
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001147#ifndef SSL_CTX_get_tlsext_status_cb
1148# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1149 *cb = (void (*) (void))ctx->tlsext_status_cb;
1150#endif
1151 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1152
1153 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001154 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001155 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001156
1157 cb_arg->is_single = 1;
1158 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001159
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001160 pkey = X509_get_pubkey(x);
1161 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1162 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001163
1164 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1165 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1166 } else {
1167 /*
1168 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1169 * Update that cb_arg with the new cert's staple
1170 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001171 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001172 struct certificate_ocsp *tmp_ocsp;
1173 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001174 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001175 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001176
1177#ifdef SSL_CTX_get_tlsext_status_arg
1178 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1179#else
1180 cb_arg = ctx->tlsext_status_arg;
1181#endif
yanbzhube2774d2015-12-10 15:07:30 -05001182
1183 /*
1184 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1185 * the order of operations below matter, take care when changing it
1186 */
1187 tmp_ocsp = cb_arg->s_ocsp;
1188 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1189 cb_arg->s_ocsp = NULL;
1190 cb_arg->m_ocsp[index] = tmp_ocsp;
1191 cb_arg->is_single = 0;
1192 cb_arg->single_kt = 0;
1193
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001194 pkey = X509_get_pubkey(x);
1195 key_type = EVP_PKEY_base_id(pkey);
1196 EVP_PKEY_free(pkey);
1197
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001198 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001199 if (index >= 0 && !cb_arg->m_ocsp[index])
1200 cb_arg->m_ocsp[index] = iocsp;
1201
1202 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001203
1204 ret = 0;
1205
1206 warn = NULL;
1207 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1208 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001209 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001210 }
1211
1212out:
1213 if (ssl)
1214 SSL_free(ssl);
1215
1216 if (in)
1217 BIO_free(in);
1218
1219 if (xi)
1220 X509_free(xi);
1221
1222 if (cid)
1223 OCSP_CERTID_free(cid);
1224
1225 if (ocsp)
1226 free(ocsp);
1227
1228 if (warn)
1229 free(warn);
1230
1231
1232 return ret;
1233}
1234
1235#endif
1236
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001237#ifdef OPENSSL_IS_BORINGSSL
1238static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1239{
1240 char ocsp_path[MAXPATHLEN+1];
1241 struct stat st;
1242 int fd = -1, r = 0;
1243
1244 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1245 if (stat(ocsp_path, &st))
1246 return 0;
1247
1248 fd = open(ocsp_path, O_RDONLY);
1249 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001250 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001251 return -1;
1252 }
1253
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001254 trash.data = 0;
1255 while (trash.data < trash.size) {
1256 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001257 if (r < 0) {
1258 if (errno == EINTR)
1259 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001260 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001261 close(fd);
1262 return -1;
1263 }
1264 else if (r == 0) {
1265 break;
1266 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001267 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001268 }
1269 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001270 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1271 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001272}
1273#endif
1274
Daniel Jakots54ffb912015-11-06 20:02:41 +01001275#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001276
1277#define CT_EXTENSION_TYPE 18
1278
1279static int sctl_ex_index = -1;
1280
1281/*
1282 * Try to parse Signed Certificate Timestamp List structure. This function
1283 * makes only basic test if the data seems like SCTL. No signature validation
1284 * is performed.
1285 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001286static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001287{
1288 int ret = 1;
1289 int len, pos, sct_len;
1290 unsigned char *data;
1291
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001292 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001293 goto out;
1294
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001295 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001296 len = (data[0] << 8) | data[1];
1297
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001298 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001299 goto out;
1300
1301 data = data + 2;
1302 pos = 0;
1303 while (pos < len) {
1304 if (len - pos < 2)
1305 goto out;
1306
1307 sct_len = (data[pos] << 8) | data[pos + 1];
1308 if (pos + sct_len + 2 > len)
1309 goto out;
1310
1311 pos += sct_len + 2;
1312 }
1313
1314 ret = 0;
1315
1316out:
1317 return ret;
1318}
1319
Willy Tarreau83061a82018-07-13 11:56:34 +02001320static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1321 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001322{
1323 int fd = -1;
1324 int r = 0;
1325 int ret = 1;
1326
1327 *sctl = NULL;
1328
1329 fd = open(sctl_path, O_RDONLY);
1330 if (fd == -1)
1331 goto end;
1332
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001333 trash.data = 0;
1334 while (trash.data < trash.size) {
1335 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001336 if (r < 0) {
1337 if (errno == EINTR)
1338 continue;
1339
1340 goto end;
1341 }
1342 else if (r == 0) {
1343 break;
1344 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001345 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001346 }
1347
1348 ret = ssl_sock_parse_sctl(&trash);
1349 if (ret)
1350 goto end;
1351
Vincent Bernat02779b62016-04-03 13:48:43 +02001352 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001353 if (!chunk_dup(*sctl, &trash)) {
1354 free(*sctl);
1355 *sctl = NULL;
1356 goto end;
1357 }
1358
1359end:
1360 if (fd != -1)
1361 close(fd);
1362
1363 return ret;
1364}
1365
1366int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1367{
Willy Tarreau83061a82018-07-13 11:56:34 +02001368 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001369
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001370 *out = (unsigned char *) sctl->area;
1371 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001372
1373 return 1;
1374}
1375
1376int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1377{
1378 return 1;
1379}
1380
1381static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1382{
1383 char sctl_path[MAXPATHLEN+1];
1384 int ret = -1;
1385 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001386 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001387
1388 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1389
1390 if (stat(sctl_path, &st))
1391 return 1;
1392
1393 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1394 goto out;
1395
1396 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1397 free(sctl);
1398 goto out;
1399 }
1400
1401 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1402
1403 ret = 0;
1404
1405out:
1406 return ret;
1407}
1408
1409#endif
1410
Emeric Brune1f38db2012-09-03 20:36:47 +02001411void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1412{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001413 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001414 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001415 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001416
1417 if (where & SSL_CB_HANDSHAKE_START) {
1418 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001419 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001420 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001421 conn->err_code = CO_ER_SSL_RENEG;
1422 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001423 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001424
1425 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1426 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1427 /* Long certificate chains optimz
1428 If write and read bios are differents, we
1429 consider that the buffering was activated,
1430 so we rise the output buffer size from 4k
1431 to 16k */
1432 write_bio = SSL_get_wbio(ssl);
1433 if (write_bio != SSL_get_rbio(ssl)) {
1434 BIO_set_write_buffer_size(write_bio, 16384);
1435 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1436 }
1437 }
1438 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001439}
1440
Emeric Brune64aef12012-09-21 13:15:06 +02001441/* Callback is called for each certificate of the chain during a verify
1442 ok is set to 1 if preverify detect no error on current certificate.
1443 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001444int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001445{
1446 SSL *ssl;
1447 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001448 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001449
1450 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001451 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001452
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001453 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001454
Emeric Brun81c00f02012-09-21 14:31:21 +02001455 if (ok) /* no errors */
1456 return ok;
1457
1458 depth = X509_STORE_CTX_get_error_depth(x_store);
1459 err = X509_STORE_CTX_get_error(x_store);
1460
1461 /* check if CA error needs to be ignored */
1462 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001463 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1464 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1465 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001466 }
1467
Willy Tarreau07d94e42018-09-20 10:57:52 +02001468 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001469 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001470 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001471 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001472 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001473
Willy Tarreau20879a02012-12-03 16:32:10 +01001474 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001475 return 0;
1476 }
1477
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001478 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1479 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001480
Emeric Brun81c00f02012-09-21 14:31:21 +02001481 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001482 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001483 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001484 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001485 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001486 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001487
Willy Tarreau20879a02012-12-03 16:32:10 +01001488 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001489 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001490}
1491
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001492static inline
1493void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001494 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001495{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001496 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001497 unsigned char *msg;
1498 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001499 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001500
1501 /* This function is called for "from client" and "to server"
1502 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001503 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001504 */
1505
1506 /* "write_p" is set to 0 is the bytes are received messages,
1507 * otherwise it is set to 1.
1508 */
1509 if (write_p != 0)
1510 return;
1511
1512 /* content_type contains the type of message received or sent
1513 * according with the SSL/TLS protocol spec. This message is
1514 * encoded with one byte. The value 256 (two bytes) is used
1515 * for designing the SSL/TLS record layer. According with the
1516 * rfc6101, the expected message (other than 256) are:
1517 * - change_cipher_spec(20)
1518 * - alert(21)
1519 * - handshake(22)
1520 * - application_data(23)
1521 * - (255)
1522 * We are interessed by the handshake and specially the client
1523 * hello.
1524 */
1525 if (content_type != 22)
1526 return;
1527
1528 /* The message length is at least 4 bytes, containing the
1529 * message type and the message length.
1530 */
1531 if (len < 4)
1532 return;
1533
1534 /* First byte of the handshake message id the type of
1535 * message. The konwn types are:
1536 * - hello_request(0)
1537 * - client_hello(1)
1538 * - server_hello(2)
1539 * - certificate(11)
1540 * - server_key_exchange (12)
1541 * - certificate_request(13)
1542 * - server_hello_done(14)
1543 * We are interested by the client hello.
1544 */
1545 msg = (unsigned char *)buf;
1546 if (msg[0] != 1)
1547 return;
1548
1549 /* Next three bytes are the length of the message. The total length
1550 * must be this decoded length + 4. If the length given as argument
1551 * is not the same, we abort the protocol dissector.
1552 */
1553 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1554 if (len < rec_len + 4)
1555 return;
1556 msg += 4;
1557 end = msg + rec_len;
1558 if (end < msg)
1559 return;
1560
1561 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1562 * for minor, the random, composed by 4 bytes for the unix time and
1563 * 28 bytes for unix payload, and them 1 byte for the session id. So
1564 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1565 */
1566 msg += 1 + 1 + 4 + 28 + 1;
1567 if (msg > end)
1568 return;
1569
1570 /* Next two bytes are the ciphersuite length. */
1571 if (msg + 2 > end)
1572 return;
1573 rec_len = (msg[0] << 8) + msg[1];
1574 msg += 2;
1575 if (msg + rec_len > end || msg + rec_len < msg)
1576 return;
1577
Willy Tarreaubafbe012017-11-24 17:34:44 +01001578 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001579 if (!capture)
1580 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001581 /* Compute the xxh64 of the ciphersuite. */
1582 capture->xxh64 = XXH64(msg, rec_len, 0);
1583
1584 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001585 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1586 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001587 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001588
1589 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001590}
1591
Emeric Brun29f037d2014-04-25 19:05:36 +02001592/* Callback is called for ssl protocol analyse */
1593void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1594{
Emeric Brun29f037d2014-04-25 19:05:36 +02001595#ifdef TLS1_RT_HEARTBEAT
1596 /* test heartbeat received (write_p is set to 0
1597 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001598 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001599 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001600 const unsigned char *p = buf;
1601 unsigned int payload;
1602
Emeric Brun29f037d2014-04-25 19:05:36 +02001603 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001604
1605 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1606 if (*p != TLS1_HB_REQUEST)
1607 return;
1608
Willy Tarreauaeed6722014-04-25 23:59:58 +02001609 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001610 goto kill_it;
1611
1612 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001613 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001614 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001615 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001616 /* We have a clear heartbleed attack (CVE-2014-0160), the
1617 * advertised payload is larger than the advertised packet
1618 * length, so we have garbage in the buffer between the
1619 * payload and the end of the buffer (p+len). We can't know
1620 * if the SSL stack is patched, and we don't know if we can
1621 * safely wipe out the area between p+3+len and payload.
1622 * So instead, we prevent the response from being sent by
1623 * setting the max_send_fragment to 0 and we report an SSL
1624 * error, which will kill this connection. It will be reported
1625 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001626 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1627 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001628 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001629 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1630 return;
1631 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001632#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001633 if (global_ssl.capture_cipherlist > 0)
1634 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001635}
1636
Bernard Spil13c53f82018-02-15 13:34:58 +01001637#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001638/* This callback is used so that the server advertises the list of
1639 * negociable protocols for NPN.
1640 */
1641static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1642 unsigned int *len, void *arg)
1643{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001644 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001645
1646 *data = (const unsigned char *)conf->npn_str;
1647 *len = conf->npn_len;
1648 return SSL_TLSEXT_ERR_OK;
1649}
1650#endif
1651
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001652#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001653/* This callback is used so that the server advertises the list of
1654 * negociable protocols for ALPN.
1655 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001656static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1657 unsigned char *outlen,
1658 const unsigned char *server,
1659 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001660{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001661 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001662
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001663 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1664 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1665 return SSL_TLSEXT_ERR_NOACK;
1666 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001667 return SSL_TLSEXT_ERR_OK;
1668}
1669#endif
1670
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001671#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001672#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001673
Christopher Faulet30548802015-06-11 13:39:32 +02001674/* Create a X509 certificate with the specified servername and serial. This
1675 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001676static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001677ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001678{
Christopher Faulet7969a332015-10-09 11:15:03 +02001679 X509 *cacert = bind_conf->ca_sign_cert;
1680 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001681 SSL_CTX *ssl_ctx = NULL;
1682 X509 *newcrt = NULL;
1683 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001684 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001685 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001686 X509_NAME *name;
1687 const EVP_MD *digest;
1688 X509V3_CTX ctx;
1689 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001690 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001691
Christopher Faulet48a83322017-07-28 16:56:09 +02001692 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001693#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1694 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1695#else
1696 tmp_ssl = SSL_new(bind_conf->default_ctx);
1697 if (tmp_ssl)
1698 pkey = SSL_get_privatekey(tmp_ssl);
1699#endif
1700 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001701 goto mkcert_error;
1702
1703 /* Create the certificate */
1704 if (!(newcrt = X509_new()))
1705 goto mkcert_error;
1706
1707 /* Set version number for the certificate (X509v3) and the serial
1708 * number */
1709 if (X509_set_version(newcrt, 2L) != 1)
1710 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001711 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001712
1713 /* Set duration for the certificate */
1714 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1715 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1716 goto mkcert_error;
1717
1718 /* set public key in the certificate */
1719 if (X509_set_pubkey(newcrt, pkey) != 1)
1720 goto mkcert_error;
1721
1722 /* Set issuer name from the CA */
1723 if (!(name = X509_get_subject_name(cacert)))
1724 goto mkcert_error;
1725 if (X509_set_issuer_name(newcrt, name) != 1)
1726 goto mkcert_error;
1727
1728 /* Set the subject name using the same, but the CN */
1729 name = X509_NAME_dup(name);
1730 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1731 (const unsigned char *)servername,
1732 -1, -1, 0) != 1) {
1733 X509_NAME_free(name);
1734 goto mkcert_error;
1735 }
1736 if (X509_set_subject_name(newcrt, name) != 1) {
1737 X509_NAME_free(name);
1738 goto mkcert_error;
1739 }
1740 X509_NAME_free(name);
1741
1742 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001743 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001744 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1745 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1746 X509_EXTENSION *ext;
1747
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001748 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001749 goto mkcert_error;
1750 if (!X509_add_ext(newcrt, ext, -1)) {
1751 X509_EXTENSION_free(ext);
1752 goto mkcert_error;
1753 }
1754 X509_EXTENSION_free(ext);
1755 }
1756
1757 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001758
1759 key_type = EVP_PKEY_base_id(capkey);
1760
1761 if (key_type == EVP_PKEY_DSA)
1762 digest = EVP_sha1();
1763 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001764 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001765 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001766 digest = EVP_sha256();
1767 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001768#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001769 int nid;
1770
1771 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1772 goto mkcert_error;
1773 if (!(digest = EVP_get_digestbynid(nid)))
1774 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001775#else
1776 goto mkcert_error;
1777#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001778 }
1779
Christopher Faulet31af49d2015-06-09 17:29:50 +02001780 if (!(X509_sign(newcrt, capkey, digest)))
1781 goto mkcert_error;
1782
1783 /* Create and set the new SSL_CTX */
1784 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1785 goto mkcert_error;
1786 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1787 goto mkcert_error;
1788 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1789 goto mkcert_error;
1790 if (!SSL_CTX_check_private_key(ssl_ctx))
1791 goto mkcert_error;
1792
1793 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001794
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001795#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001796 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001797#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001798#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1799 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001800 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001801 EC_KEY *ecc;
1802 int nid;
1803
1804 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1805 goto end;
1806 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1807 goto end;
1808 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1809 EC_KEY_free(ecc);
1810 }
1811#endif
1812 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001813 return ssl_ctx;
1814
1815 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001816 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001817 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001818 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1819 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001820 return NULL;
1821}
1822
Christopher Faulet7969a332015-10-09 11:15:03 +02001823SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001824ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001825{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001826 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001827
1828 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001829}
1830
Christopher Faulet30548802015-06-11 13:39:32 +02001831/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001832 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001833SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001834ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001835{
1836 struct lru64 *lru = NULL;
1837
1838 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001839 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001840 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001841 if (lru && lru->domain) {
1842 if (ssl)
1843 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001844 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001845 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001846 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001847 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001848 }
1849 return NULL;
1850}
1851
Emeric Brun821bb9b2017-06-15 16:37:39 +02001852/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1853 * function is not thread-safe, it should only be used to check if a certificate
1854 * exists in the lru cache (with no warranty it will not be removed by another
1855 * thread). It is kept for backward compatibility. */
1856SSL_CTX *
1857ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1858{
1859 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1860}
1861
Christopher Fauletd2cab922015-07-28 16:03:47 +02001862/* Set a certificate int the LRU cache used to store generated
1863 * certificate. Return 0 on success, otherwise -1 */
1864int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001865ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001866{
1867 struct lru64 *lru = NULL;
1868
1869 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001870 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001871 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001872 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001873 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001874 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001875 }
Christopher Faulet30548802015-06-11 13:39:32 +02001876 if (lru->domain && lru->data)
1877 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001878 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001879 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001880 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001881 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001882 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001883}
1884
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001885/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001886unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001887ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001888{
1889 return XXH32(data, len, ssl_ctx_lru_seed);
1890}
1891
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001892/* Generate a cert and immediately assign it to the SSL session so that the cert's
1893 * refcount is maintained regardless of the cert's presence in the LRU cache.
1894 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001895static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001896ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001897{
1898 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001899 SSL_CTX *ssl_ctx = NULL;
1900 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001901 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001902
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001903 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001904 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001905 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001906 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001907 if (lru && lru->domain)
1908 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001909 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001910 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001911 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001912 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001913 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001914 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001915 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001916 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001917 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001918 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001919 SSL_set_SSL_CTX(ssl, ssl_ctx);
1920 /* No LRU cache, this CTX will be released as soon as the session dies */
1921 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001922 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001923 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001924 return 0;
1925}
1926static int
1927ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1928{
1929 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001930 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001931
1932 conn_get_to_addr(conn);
1933 if (conn->flags & CO_FL_ADDR_TO_SET) {
1934 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001935 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001936 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001937 }
1938 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001939}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001940#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001941
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001942
1943#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1944#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1945#endif
1946
1947#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1948#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1949#define SSL_renegotiate_pending(arg) 0
1950#endif
1951#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1952#define SSL_OP_SINGLE_ECDH_USE 0
1953#endif
1954#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1955#define SSL_OP_NO_TICKET 0
1956#endif
1957#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1958#define SSL_OP_NO_COMPRESSION 0
1959#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001960#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1961#undef SSL_OP_NO_SSLv3
1962#define SSL_OP_NO_SSLv3 0
1963#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001964#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1965#define SSL_OP_NO_TLSv1_1 0
1966#endif
1967#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1968#define SSL_OP_NO_TLSv1_2 0
1969#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001970#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001971#define SSL_OP_NO_TLSv1_3 0
1972#endif
1973#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1974#define SSL_OP_SINGLE_DH_USE 0
1975#endif
1976#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1977#define SSL_OP_SINGLE_ECDH_USE 0
1978#endif
1979#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1980#define SSL_MODE_RELEASE_BUFFERS 0
1981#endif
1982#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1983#define SSL_MODE_SMALL_BUFFERS 0
1984#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02001985#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
1986#define SSL_OP_PRIORITIZE_CHACHA 0
1987#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001988
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001989#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001990typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1991
1992static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001993{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001994#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001995 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001996 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1997#endif
1998}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001999static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2000 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002001 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2002}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002003static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002004#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002005 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002006 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2007#endif
2008}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002010#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002011 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2013#endif
2014}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002015/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002016static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2017/* Unusable in this context. */
2018static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2019static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2020static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2021static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2022static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002023#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002024typedef enum { SET_MIN, SET_MAX } set_context_func;
2025
2026static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2027 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2029}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002030static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2031 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2032 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2033}
2034static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2035 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002036 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2037}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002038static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2039 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2040 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2041}
2042static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2043 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002044 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2045}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002046static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2047 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2048 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2049}
2050static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2051 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002052 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2053}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2055 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2056 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2057}
2058static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002059#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002060 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002061 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2062#endif
2063}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002064static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2065#if SSL_OP_NO_TLSv1_3
2066 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2067 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002068#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002069}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002070#endif
2071static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2072static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002073
2074static struct {
2075 int option;
2076 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002077 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2078 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002079 const char *name;
2080} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002081 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2082 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2083 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2084 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2085 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2086 {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 +02002087};
2088
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002089static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2090{
2091 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2092 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2093 SSL_set_SSL_CTX(ssl, ctx);
2094}
2095
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002096#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002097
2098static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2099{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002100 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002101 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002102
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002103 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2104 return SSL_TLSEXT_ERR_OK;
2105 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002106}
2107
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002108#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002109static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2110{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002111 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002112#else
2113static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2114{
2115#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116 struct connection *conn;
2117 struct bind_conf *s;
2118 const uint8_t *extension_data;
2119 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002120 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121
2122 char *wildp = NULL;
2123 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002124 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002126 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002127 int i;
2128
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002129 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002130 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131
Olivier Houchard9679ac92017-10-27 14:58:08 +02002132 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002133 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002134#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002135 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2136 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002137#else
2138 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2139#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002140 /*
2141 * The server_name extension was given too much extensibility when it
2142 * was written, so parsing the normal case is a bit complex.
2143 */
2144 size_t len;
2145 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002147 /* Extract the length of the supplied list of names. */
2148 len = (*extension_data++) << 8;
2149 len |= *extension_data++;
2150 if (len + 2 != extension_len)
2151 goto abort;
2152 /*
2153 * The list in practice only has a single element, so we only consider
2154 * the first one.
2155 */
2156 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2157 goto abort;
2158 extension_len = len - 1;
2159 /* Now we can finally pull out the byte array with the actual hostname. */
2160 if (extension_len <= 2)
2161 goto abort;
2162 len = (*extension_data++) << 8;
2163 len |= *extension_data++;
2164 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2165 || memchr(extension_data, 0, len) != NULL)
2166 goto abort;
2167 servername = extension_data;
2168 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002169 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002170#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2171 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002172 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002173 }
2174#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002175 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002176 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002177 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002178 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002179 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002180 goto abort;
2181 }
2182
2183 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002184#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002185 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002186#else
2187 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2188#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002189 uint8_t sign;
2190 size_t len;
2191 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002192 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002193 len = (*extension_data++) << 8;
2194 len |= *extension_data++;
2195 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002196 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002197 if (len % 2 != 0)
2198 goto abort;
2199 for (; len > 0; len -= 2) {
2200 extension_data++; /* hash */
2201 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002202 switch (sign) {
2203 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002204 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002205 break;
2206 case TLSEXT_signature_ecdsa:
2207 has_ecdsa_sig = 1;
2208 break;
2209 default:
2210 continue;
2211 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002212 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002213 break;
2214 }
2215 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002216 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002217 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002218 }
2219 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002220 const SSL_CIPHER *cipher;
2221 size_t len;
2222 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002223 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002224#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002225 len = ctx->cipher_suites_len;
2226 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002227#else
2228 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2229#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002230 if (len % 2 != 0)
2231 goto abort;
2232 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002233#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002234 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002235 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002236#else
2237 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2238#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002239 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002240 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002241 break;
2242 }
2243 }
2244 }
2245
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002246 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002247 trash.area[i] = tolower(servername[i]);
2248 if (!wildp && (trash.area[i] == '.'))
2249 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002250 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002251 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002252
2253 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002254 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002255
2256 /* lookup a not neg filter */
2257 for (n = node; n; n = ebmb_next_dup(n)) {
2258 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002259 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002260 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002261 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002262 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002263 break;
2264 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002265 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002266 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002267 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002268 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002269 if (!node_anonymous)
2270 node_anonymous = n;
2271 break;
2272 }
2273 }
2274 }
2275 if (wildp) {
2276 /* lookup in wildcards names */
2277 node = ebst_lookup(&s->sni_w_ctx, wildp);
2278 for (n = node; n; n = ebmb_next_dup(n)) {
2279 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002280 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002282 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 break;
2285 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002286 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002288 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002289 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002290 if (!node_anonymous)
2291 node_anonymous = n;
2292 break;
2293 }
2294 }
2295 }
2296 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002297 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002298 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2299 : ((has_rsa_sig && node_rsa) ? node_rsa
2300 : (node_anonymous ? node_anonymous
2301 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2302 : node_rsa /* no rsa signature case (far far away) */
2303 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 if (node) {
2305 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002306 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002307 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002308 if (conf) {
2309 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2310 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2311 if (conf->early_data)
2312 allow_early = 1;
2313 }
2314 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002315 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002316#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002317 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002318 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002319 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002320 }
2321#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002322 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002323 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002324 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002325 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002326allow_early:
2327#ifdef OPENSSL_IS_BORINGSSL
2328 if (allow_early)
2329 SSL_set_early_data_enabled(ssl, 1);
2330#else
2331 if (!allow_early)
2332 SSL_set_max_early_data(ssl, 0);
2333#endif
2334 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002335 abort:
2336 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2337 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002338#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002339 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002340#else
2341 *al = SSL_AD_UNRECOGNIZED_NAME;
2342 return 0;
2343#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002344}
2345
2346#else /* OPENSSL_IS_BORINGSSL */
2347
Emeric Brunfc0421f2012-09-07 17:30:07 +02002348/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2349 * warning when no match is found, which implies the default (first) cert
2350 * will keep being used.
2351 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002352static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002353{
2354 const char *servername;
2355 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002356 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002357 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002358 int i;
2359 (void)al; /* shut gcc stupid warning */
2360
2361 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002362 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002363#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002364 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2365 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002366#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002367 if (s->strict_sni)
2368 return SSL_TLSEXT_ERR_ALERT_FATAL;
2369 ssl_sock_switchctx_set(ssl, s->default_ctx);
2370 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002371 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002373 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002374 if (!servername[i])
2375 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002376 trash.area[i] = tolower(servername[i]);
2377 if (!wildp && (trash.area[i] == '.'))
2378 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002379 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002380 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002381
2382 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002383 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002384
2385 /* lookup a not neg filter */
2386 for (n = node; n; n = ebmb_next_dup(n)) {
2387 if (!container_of(n, struct sni_ctx, name)->neg) {
2388 node = n;
2389 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002390 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002391 }
2392 if (!node && wildp) {
2393 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002394 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002395 }
2396 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002397#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002398 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2399 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002400 return SSL_TLSEXT_ERR_OK;
2401 }
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_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002407 }
2408
2409 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002410 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002411 return SSL_TLSEXT_ERR_OK;
2412}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002413#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002414#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2415
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002416#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002417
2418static DH * ssl_get_dh_1024(void)
2419{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002420 static unsigned char dh1024_p[]={
2421 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2422 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2423 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2424 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2425 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2426 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2427 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2428 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2429 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2430 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2431 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2432 };
2433 static unsigned char dh1024_g[]={
2434 0x02,
2435 };
2436
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002437 BIGNUM *p;
2438 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002439 DH *dh = DH_new();
2440 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002441 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2442 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002443
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002444 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002445 DH_free(dh);
2446 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002447 } else {
2448 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002449 }
2450 }
2451 return dh;
2452}
2453
2454static DH *ssl_get_dh_2048(void)
2455{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002456 static unsigned char dh2048_p[]={
2457 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2458 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2459 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2460 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2461 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2462 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2463 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2464 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2465 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2466 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2467 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2468 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2469 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2470 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2471 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2472 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2473 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2474 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2475 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2476 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2477 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2478 0xB7,0x1F,0x77,0xF3,
2479 };
2480 static unsigned char dh2048_g[]={
2481 0x02,
2482 };
2483
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002484 BIGNUM *p;
2485 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002486 DH *dh = DH_new();
2487 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002488 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2489 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002490
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002491 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002492 DH_free(dh);
2493 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002494 } else {
2495 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002496 }
2497 }
2498 return dh;
2499}
2500
2501static DH *ssl_get_dh_4096(void)
2502{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002503 static unsigned char dh4096_p[]={
2504 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2505 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2506 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2507 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2508 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2509 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2510 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2511 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2512 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2513 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2514 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2515 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2516 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2517 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2518 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2519 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2520 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2521 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2522 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2523 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2524 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2525 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2526 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2527 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2528 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2529 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2530 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2531 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2532 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2533 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2534 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2535 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2536 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2537 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2538 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2539 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2540 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2541 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2542 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2543 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2544 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2545 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2546 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002547 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002548 static unsigned char dh4096_g[]={
2549 0x02,
2550 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002551
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002552 BIGNUM *p;
2553 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002554 DH *dh = DH_new();
2555 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002556 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2557 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002558
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002559 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002560 DH_free(dh);
2561 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002562 } else {
2563 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002564 }
2565 }
2566 return dh;
2567}
2568
2569/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002570 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002571static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2572{
2573 DH *dh = NULL;
2574 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002575 int type;
2576
2577 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578
2579 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2580 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2581 */
2582 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2583 keylen = EVP_PKEY_bits(pkey);
2584 }
2585
Willy Tarreauef934602016-12-22 23:12:01 +01002586 if (keylen > global_ssl.default_dh_param) {
2587 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002588 }
2589
Remi Gacogned3a341a2015-05-29 16:26:17 +02002590 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002591 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002592 }
2593 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002594 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002595 }
2596 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002597 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002598 }
2599
2600 return dh;
2601}
2602
Remi Gacogne47783ef2015-05-29 15:53:22 +02002603static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002604{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002605 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002606 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002607
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002608 if (in == NULL)
2609 goto end;
2610
Remi Gacogne47783ef2015-05-29 15:53:22 +02002611 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002612 goto end;
2613
Remi Gacogne47783ef2015-05-29 15:53:22 +02002614 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2615
2616end:
2617 if (in)
2618 BIO_free(in);
2619
Emeric Brune1b4ed42018-08-16 15:14:12 +02002620 ERR_clear_error();
2621
Remi Gacogne47783ef2015-05-29 15:53:22 +02002622 return dh;
2623}
2624
2625int ssl_sock_load_global_dh_param_from_file(const char *filename)
2626{
2627 global_dh = ssl_sock_get_dh_from_file(filename);
2628
2629 if (global_dh) {
2630 return 0;
2631 }
2632
2633 return -1;
2634}
2635
2636/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002637 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002638int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2639{
2640 int ret = -1;
2641 DH *dh = ssl_sock_get_dh_from_file(file);
2642
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002643 if (dh) {
2644 ret = 1;
2645 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002646
2647 if (ssl_dh_ptr_index >= 0) {
2648 /* store a pointer to the DH params to avoid complaining about
2649 ssl-default-dh-param not being set for this SSL_CTX */
2650 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2651 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002652 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002653 else if (global_dh) {
2654 SSL_CTX_set_tmp_dh(ctx, global_dh);
2655 ret = 0; /* DH params not found */
2656 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002657 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002658 /* Clear openssl global errors stack */
2659 ERR_clear_error();
2660
Willy Tarreauef934602016-12-22 23:12:01 +01002661 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002662 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002663 if (local_dh_1024 == NULL)
2664 local_dh_1024 = ssl_get_dh_1024();
2665
Remi Gacogne8de54152014-07-15 11:36:40 +02002666 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002667 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002668
Remi Gacogne8de54152014-07-15 11:36:40 +02002669 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002670 }
2671 else {
2672 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2673 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002674
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002675 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002676 }
Emeric Brun644cde02012-12-14 11:21:13 +01002677
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002678end:
2679 if (dh)
2680 DH_free(dh);
2681
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002682 return ret;
2683}
2684#endif
2685
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002686static 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 +02002687 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002688{
2689 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002690 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002691 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002692
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002693 if (*name == '!') {
2694 neg = 1;
2695 name++;
2696 }
2697 if (*name == '*') {
2698 wild = 1;
2699 name++;
2700 }
2701 /* !* filter is a nop */
2702 if (neg && wild)
2703 return order;
2704 if (*name) {
2705 int j, len;
2706 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002707 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002708 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002709 if (j >= trash.size)
2710 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002711 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002712
2713 /* Check for duplicates. */
2714 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002715 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002716 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002717 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002718 for (; node; node = ebmb_next_dup(node)) {
2719 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002720 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002721 return order;
2722 }
2723
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002724 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002725 if (!sc)
2726 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002727 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002728 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002729 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002730 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002731 sc->order = order++;
2732 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002733 if (kinfo.sig != TLSEXT_signature_anonymous)
2734 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002735 if (wild)
2736 ebst_insert(&s->sni_w_ctx, &sc->name);
2737 else
2738 ebst_insert(&s->sni_ctx, &sc->name);
2739 }
2740 return order;
2741}
2742
yanbzhu488a4d22015-12-01 15:16:07 -05002743
2744/* The following code is used for loading multiple crt files into
2745 * SSL_CTX's based on CN/SAN
2746 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002747#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002748/* This is used to preload the certifcate, private key
2749 * and Cert Chain of a file passed in via the crt
2750 * argument
2751 *
2752 * This way, we do not have to read the file multiple times
2753 */
2754struct cert_key_and_chain {
2755 X509 *cert;
2756 EVP_PKEY *key;
2757 unsigned int num_chain_certs;
2758 /* This is an array of X509 pointers */
2759 X509 **chain_certs;
2760};
2761
yanbzhu08ce6ab2015-12-02 13:01:29 -05002762#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2763
2764struct key_combo_ctx {
2765 SSL_CTX *ctx;
2766 int order;
2767};
2768
2769/* Map used for processing multiple keypairs for a single purpose
2770 *
2771 * This maps CN/SNI name to certificate type
2772 */
2773struct sni_keytype {
2774 int keytypes; /* BITMASK for keytypes */
2775 struct ebmb_node name; /* node holding the servername value */
2776};
2777
2778
yanbzhu488a4d22015-12-01 15:16:07 -05002779/* Frees the contents of a cert_key_and_chain
2780 */
2781static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2782{
2783 int i;
2784
2785 if (!ckch)
2786 return;
2787
2788 /* Free the certificate and set pointer to NULL */
2789 if (ckch->cert)
2790 X509_free(ckch->cert);
2791 ckch->cert = NULL;
2792
2793 /* Free the key and set pointer to NULL */
2794 if (ckch->key)
2795 EVP_PKEY_free(ckch->key);
2796 ckch->key = NULL;
2797
2798 /* Free each certificate in the chain */
2799 for (i = 0; i < ckch->num_chain_certs; i++) {
2800 if (ckch->chain_certs[i])
2801 X509_free(ckch->chain_certs[i]);
2802 }
2803
2804 /* Free the chain obj itself and set to NULL */
2805 if (ckch->num_chain_certs > 0) {
2806 free(ckch->chain_certs);
2807 ckch->num_chain_certs = 0;
2808 ckch->chain_certs = NULL;
2809 }
2810
2811}
2812
2813/* checks if a key and cert exists in the ckch
2814 */
2815static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2816{
2817 return (ckch->cert != NULL && ckch->key != NULL);
2818}
2819
2820
2821/* Loads the contents of a crt file (path) into a cert_key_and_chain
2822 * This allows us to carry the contents of the file without having to
2823 * read the file multiple times.
2824 *
2825 * returns:
2826 * 0 on Success
2827 * 1 on SSL Failure
2828 * 2 on file not found
2829 */
2830static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2831{
2832
2833 BIO *in;
2834 X509 *ca = NULL;
2835 int ret = 1;
2836
2837 ssl_sock_free_cert_key_and_chain_contents(ckch);
2838
2839 in = BIO_new(BIO_s_file());
2840 if (in == NULL)
2841 goto end;
2842
2843 if (BIO_read_filename(in, path) <= 0)
2844 goto end;
2845
yanbzhu488a4d22015-12-01 15:16:07 -05002846 /* Read Private Key */
2847 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2848 if (ckch->key == NULL) {
2849 memprintf(err, "%sunable to load private key from file '%s'.\n",
2850 err && *err ? *err : "", path);
2851 goto end;
2852 }
2853
Willy Tarreaubb137a82016-04-06 19:02:38 +02002854 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002855 if (BIO_reset(in) == -1) {
2856 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2857 err && *err ? *err : "", path);
2858 goto end;
2859 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002860
2861 /* Read Certificate */
2862 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2863 if (ckch->cert == NULL) {
2864 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2865 err && *err ? *err : "", path);
2866 goto end;
2867 }
2868
yanbzhu488a4d22015-12-01 15:16:07 -05002869 /* Read Certificate Chain */
2870 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2871 /* Grow the chain certs */
2872 ckch->num_chain_certs++;
2873 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2874
2875 /* use - 1 here since we just incremented it above */
2876 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2877 }
2878 ret = ERR_get_error();
2879 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2880 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2881 err && *err ? *err : "", path);
2882 ret = 1;
2883 goto end;
2884 }
2885
2886 ret = 0;
2887
2888end:
2889
2890 ERR_clear_error();
2891 if (in)
2892 BIO_free(in);
2893
2894 /* Something went wrong in one of the reads */
2895 if (ret != 0)
2896 ssl_sock_free_cert_key_and_chain_contents(ckch);
2897
2898 return ret;
2899}
2900
2901/* Loads the info in ckch into ctx
2902 * Currently, this does not process any information about ocsp, dhparams or
2903 * sctl
2904 * Returns
2905 * 0 on success
2906 * 1 on failure
2907 */
2908static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2909{
2910 int i = 0;
2911
2912 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2913 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2914 err && *err ? *err : "", path);
2915 return 1;
2916 }
2917
2918 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2919 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2920 err && *err ? *err : "", path);
2921 return 1;
2922 }
2923
yanbzhu488a4d22015-12-01 15:16:07 -05002924 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2925 for (i = 0; i < ckch->num_chain_certs; i++) {
2926 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002927 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2928 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002929 return 1;
2930 }
2931 }
2932
2933 if (SSL_CTX_check_private_key(ctx) <= 0) {
2934 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2935 err && *err ? *err : "", path);
2936 return 1;
2937 }
2938
2939 return 0;
2940}
2941
yanbzhu08ce6ab2015-12-02 13:01:29 -05002942
2943static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2944{
2945 struct sni_keytype *s_kt = NULL;
2946 struct ebmb_node *node;
2947 int i;
2948
2949 for (i = 0; i < trash.size; i++) {
2950 if (!str[i])
2951 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002952 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002953 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002954 trash.area[i] = 0;
2955 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002956 if (!node) {
2957 /* CN not found in tree */
2958 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2959 /* Using memcpy here instead of strncpy.
2960 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2961 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2962 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002963 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002964 s_kt->keytypes = 0;
2965 ebst_insert(sni_keytypes, &s_kt->name);
2966 } else {
2967 /* CN found in tree */
2968 s_kt = container_of(node, struct sni_keytype, name);
2969 }
2970
2971 /* Mark that this CN has the keytype of key_index via keytypes mask */
2972 s_kt->keytypes |= 1<<key_index;
2973
2974}
2975
2976
2977/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2978 * If any are found, group these files into a set of SSL_CTX*
2979 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2980 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08002981 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05002982 *
2983 * Returns
2984 * 0 on success
2985 * 1 on failure
2986 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002987static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2988 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002989{
2990 char fp[MAXPATHLEN+1] = {0};
2991 int n = 0;
2992 int i = 0;
2993 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2994 struct eb_root sni_keytypes_map = { {0} };
2995 struct ebmb_node *node;
2996 struct ebmb_node *next;
2997 /* Array of SSL_CTX pointers corresponding to each possible combo
2998 * of keytypes
2999 */
3000 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3001 int rv = 0;
3002 X509_NAME *xname = NULL;
3003 char *str = NULL;
3004#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3005 STACK_OF(GENERAL_NAME) *names = NULL;
3006#endif
3007
3008 /* Load all possible certs and keys */
3009 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3010 struct stat buf;
3011
3012 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3013 if (stat(fp, &buf) == 0) {
3014 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3015 rv = 1;
3016 goto end;
3017 }
3018 }
3019 }
3020
3021 /* Process each ckch and update keytypes for each CN/SAN
3022 * for example, if CN/SAN www.a.com is associated with
3023 * certs with keytype 0 and 2, then at the end of the loop,
3024 * www.a.com will have:
3025 * keyindex = 0 | 1 | 4 = 5
3026 */
3027 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3028
3029 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3030 continue;
3031
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003032 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003033 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003034 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3035 } else {
3036 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3037 * so the line that contains logic is marked via comments
3038 */
3039 xname = X509_get_subject_name(certs_and_keys[n].cert);
3040 i = -1;
3041 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3042 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003043 ASN1_STRING *value;
3044 value = X509_NAME_ENTRY_get_data(entry);
3045 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003046 /* Important line is here */
3047 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003048
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003049 OPENSSL_free(str);
3050 str = NULL;
3051 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003052 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003053
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003054 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003055#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003056 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3057 if (names) {
3058 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3059 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003060
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003061 if (name->type == GEN_DNS) {
3062 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3063 /* Important line is here */
3064 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003065
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003066 OPENSSL_free(str);
3067 str = NULL;
3068 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003069 }
3070 }
3071 }
3072 }
3073#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3074 }
3075
3076 /* If no files found, return error */
3077 if (eb_is_empty(&sni_keytypes_map)) {
3078 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3079 err && *err ? *err : "", path);
3080 rv = 1;
3081 goto end;
3082 }
3083
3084 /* We now have a map of CN/SAN to keytypes that are loaded in
3085 * Iterate through the map to create the SSL_CTX's (if needed)
3086 * and add each CTX to the SNI tree
3087 *
3088 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003089 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003090 * combination is denoted by the key in the map. Each key
3091 * has a value between 1 and 2^n - 1. Conveniently, the array
3092 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3093 * entry in the array to correspond to the unique combo (key)
3094 * associated with i. This unique key combo (i) will be associated
3095 * with combos[i-1]
3096 */
3097
3098 node = ebmb_first(&sni_keytypes_map);
3099 while (node) {
3100 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003101 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003102 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003103
3104 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3105 i = container_of(node, struct sni_keytype, name)->keytypes;
3106 cur_ctx = key_combos[i-1].ctx;
3107
3108 if (cur_ctx == NULL) {
3109 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003110 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003111 if (cur_ctx == NULL) {
3112 memprintf(err, "%sunable to allocate SSL context.\n",
3113 err && *err ? *err : "");
3114 rv = 1;
3115 goto end;
3116 }
3117
yanbzhube2774d2015-12-10 15:07:30 -05003118 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003119 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3120 if (i & (1<<n)) {
3121 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003122 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3123 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003124 SSL_CTX_free(cur_ctx);
3125 rv = 1;
3126 goto end;
3127 }
yanbzhube2774d2015-12-10 15:07:30 -05003128
3129#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3130 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003131 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003132 if (err)
3133 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 +00003134 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003135 SSL_CTX_free(cur_ctx);
3136 rv = 1;
3137 goto end;
3138 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003139#elif (defined OPENSSL_IS_BORINGSSL)
3140 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003141#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003142 }
3143 }
3144
3145 /* Load DH params into the ctx to support DHE keys */
3146#ifndef OPENSSL_NO_DH
3147 if (ssl_dh_ptr_index >= 0)
3148 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3149
3150 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3151 if (rv < 0) {
3152 if (err)
3153 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3154 *err ? *err : "", path);
3155 rv = 1;
3156 goto end;
3157 }
3158#endif
3159
3160 /* Update key_combos */
3161 key_combos[i-1].ctx = cur_ctx;
3162 }
3163
3164 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003165 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003166 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003167 node = ebmb_next(node);
3168 }
3169
3170
3171 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3172 if (!bind_conf->default_ctx) {
3173 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3174 if (key_combos[i].ctx) {
3175 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003176 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003177 break;
3178 }
3179 }
3180 }
3181
3182end:
3183
3184 if (names)
3185 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3186
3187 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3188 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3189
3190 node = ebmb_first(&sni_keytypes_map);
3191 while (node) {
3192 next = ebmb_next(node);
3193 ebmb_delete(node);
3194 node = next;
3195 }
3196
3197 return rv;
3198}
3199#else
3200/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003201static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3202 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003203{
3204 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3205 err && *err ? *err : "", path, strerror(errno));
3206 return 1;
3207}
3208
yanbzhu488a4d22015-12-01 15:16:07 -05003209#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3210
Emeric Brunfc0421f2012-09-07 17:30:07 +02003211/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3212 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3213 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003214static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3215 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003216{
3217 BIO *in;
3218 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003219 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003220 int ret = -1;
3221 int order = 0;
3222 X509_NAME *xname;
3223 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003224 pem_password_cb *passwd_cb;
3225 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003226 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003227 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003228
Emeric Brunfc0421f2012-09-07 17:30:07 +02003229#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3230 STACK_OF(GENERAL_NAME) *names;
3231#endif
3232
3233 in = BIO_new(BIO_s_file());
3234 if (in == NULL)
3235 goto end;
3236
3237 if (BIO_read_filename(in, file) <= 0)
3238 goto end;
3239
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003240
3241 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3242 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3243
3244 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003245 if (x == NULL)
3246 goto end;
3247
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003248 pkey = X509_get_pubkey(x);
3249 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003250 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003251 switch(EVP_PKEY_base_id(pkey)) {
3252 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003253 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003254 break;
3255 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003256 kinfo.sig = TLSEXT_signature_ecdsa;
3257 break;
3258 case EVP_PKEY_DSA:
3259 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003260 break;
3261 }
3262 EVP_PKEY_free(pkey);
3263 }
3264
Emeric Brun50bcecc2013-04-22 13:05:23 +02003265 if (fcount) {
3266 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003267 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003268 }
3269 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003270#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003271 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3272 if (names) {
3273 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3274 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3275 if (name->type == GEN_DNS) {
3276 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003277 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003278 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003279 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003280 }
3281 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003282 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003283 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003284#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003285 xname = X509_get_subject_name(x);
3286 i = -1;
3287 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3288 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003289 ASN1_STRING *value;
3290
3291 value = X509_NAME_ENTRY_get_data(entry);
3292 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003293 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003294 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003296 }
3297 }
3298
3299 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3300 if (!SSL_CTX_use_certificate(ctx, x))
3301 goto end;
3302
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003303#ifdef SSL_CTX_clear_extra_chain_certs
3304 SSL_CTX_clear_extra_chain_certs(ctx);
3305#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003306 if (ctx->extra_certs != NULL) {
3307 sk_X509_pop_free(ctx->extra_certs, X509_free);
3308 ctx->extra_certs = NULL;
3309 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003310#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003311
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003312 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003313 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3314 X509_free(ca);
3315 goto end;
3316 }
3317 }
3318
3319 err = ERR_get_error();
3320 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3321 /* we successfully reached the last cert in the file */
3322 ret = 1;
3323 }
3324 ERR_clear_error();
3325
3326end:
3327 if (x)
3328 X509_free(x);
3329
3330 if (in)
3331 BIO_free(in);
3332
3333 return ret;
3334}
3335
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003336static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3337 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003338{
3339 int ret;
3340 SSL_CTX *ctx;
3341
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003342 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003343 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003344 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3345 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003346 return 1;
3347 }
3348
3349 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003350 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3351 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003352 SSL_CTX_free(ctx);
3353 return 1;
3354 }
3355
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003356 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003357 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003358 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3359 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003360 if (ret < 0) /* serious error, must do that ourselves */
3361 SSL_CTX_free(ctx);
3362 return 1;
3363 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003364
3365 if (SSL_CTX_check_private_key(ctx) <= 0) {
3366 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3367 err && *err ? *err : "", path);
3368 return 1;
3369 }
3370
Emeric Brunfc0421f2012-09-07 17:30:07 +02003371 /* we must not free the SSL_CTX anymore below, since it's already in
3372 * the tree, so it will be discovered and cleaned in time.
3373 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003374#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003375 /* store a NULL pointer to indicate we have not yet loaded
3376 a custom DH param file */
3377 if (ssl_dh_ptr_index >= 0) {
3378 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3379 }
3380
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003381 ret = ssl_sock_load_dh_params(ctx, path);
3382 if (ret < 0) {
3383 if (err)
3384 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3385 *err ? *err : "", path);
3386 return 1;
3387 }
3388#endif
3389
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003390#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003391 ret = ssl_sock_load_ocsp(ctx, path);
3392 if (ret < 0) {
3393 if (err)
3394 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",
3395 *err ? *err : "", path);
3396 return 1;
3397 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003398#elif (defined OPENSSL_IS_BORINGSSL)
3399 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003400#endif
3401
Daniel Jakots54ffb912015-11-06 20:02:41 +01003402#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003403 if (sctl_ex_index >= 0) {
3404 ret = ssl_sock_load_sctl(ctx, path);
3405 if (ret < 0) {
3406 if (err)
3407 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3408 *err ? *err : "", path);
3409 return 1;
3410 }
3411 }
3412#endif
3413
Emeric Brunfc0421f2012-09-07 17:30:07 +02003414#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003415 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003416 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3417 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003418 return 1;
3419 }
3420#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003421 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003422 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003423 bind_conf->default_ssl_conf = ssl_conf;
3424 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003425
3426 return 0;
3427}
3428
Willy Tarreau03209342016-12-22 17:08:28 +01003429int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003430{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003431 struct dirent **de_list;
3432 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003433 DIR *dir;
3434 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003435 char *end;
3436 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003437 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003438#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3439 int is_bundle;
3440 int j;
3441#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003442
yanbzhu08ce6ab2015-12-02 13:01:29 -05003443 if (stat(path, &buf) == 0) {
3444 dir = opendir(path);
3445 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003446 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003447
yanbzhu08ce6ab2015-12-02 13:01:29 -05003448 /* strip trailing slashes, including first one */
3449 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3450 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003451
yanbzhu08ce6ab2015-12-02 13:01:29 -05003452 n = scandir(path, &de_list, 0, alphasort);
3453 if (n < 0) {
3454 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3455 err && *err ? *err : "", path, strerror(errno));
3456 cfgerr++;
3457 }
3458 else {
3459 for (i = 0; i < n; i++) {
3460 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003461
yanbzhu08ce6ab2015-12-02 13:01:29 -05003462 end = strrchr(de->d_name, '.');
3463 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3464 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003465
yanbzhu08ce6ab2015-12-02 13:01:29 -05003466 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3467 if (stat(fp, &buf) != 0) {
3468 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3469 err && *err ? *err : "", fp, strerror(errno));
3470 cfgerr++;
3471 goto ignore_entry;
3472 }
3473 if (!S_ISREG(buf.st_mode))
3474 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003475
3476#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3477 is_bundle = 0;
3478 /* Check if current entry in directory is part of a multi-cert bundle */
3479
3480 if (end) {
3481 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3482 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3483 is_bundle = 1;
3484 break;
3485 }
3486 }
3487
3488 if (is_bundle) {
3489 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3490 int dp_len;
3491
3492 dp_len = end - de->d_name;
3493 snprintf(dp, dp_len + 1, "%s", de->d_name);
3494
3495 /* increment i and free de until we get to a non-bundle cert
3496 * Note here that we look at de_list[i + 1] before freeing de
3497 * this is important since ignore_entry will free de
3498 */
3499 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3500 free(de);
3501 i++;
3502 de = de_list[i];
3503 }
3504
3505 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003506 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003507
3508 /* Successfully processed the bundle */
3509 goto ignore_entry;
3510 }
3511 }
3512
3513#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003514 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003515ignore_entry:
3516 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003517 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003518 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003519 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003520 closedir(dir);
3521 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003522 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003523
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003524 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003525
Emeric Brunfc0421f2012-09-07 17:30:07 +02003526 return cfgerr;
3527}
3528
Thierry Fournier383085f2013-01-24 14:15:43 +01003529/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3530 * done once. Zero is returned if the operation fails. No error is returned
3531 * if the random is said as not implemented, because we expect that openssl
3532 * will use another method once needed.
3533 */
3534static int ssl_initialize_random()
3535{
3536 unsigned char random;
3537 static int random_initialized = 0;
3538
3539 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3540 random_initialized = 1;
3541
3542 return random_initialized;
3543}
3544
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003545/* release ssl bind conf */
3546void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003547{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003548 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003549#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003550 free(conf->npn_str);
3551 conf->npn_str = NULL;
3552#endif
3553#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3554 free(conf->alpn_str);
3555 conf->alpn_str = NULL;
3556#endif
3557 free(conf->ca_file);
3558 conf->ca_file = NULL;
3559 free(conf->crl_file);
3560 conf->crl_file = NULL;
3561 free(conf->ciphers);
3562 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003563#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3564 free(conf->ciphersuites);
3565 conf->ciphersuites = NULL;
3566#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003567 free(conf->curves);
3568 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003569 free(conf->ecdhe);
3570 conf->ecdhe = NULL;
3571 }
3572}
3573
3574int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3575{
3576 char thisline[CRT_LINESIZE];
3577 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003578 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003579 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003580 int linenum = 0;
3581 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003582
Willy Tarreauad1731d2013-04-02 17:35:58 +02003583 if ((f = fopen(file, "r")) == NULL) {
3584 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003585 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003586 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003587
3588 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003589 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003590 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003591 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003592 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003593 char *crt_path;
3594 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003595
3596 linenum++;
3597 end = line + strlen(line);
3598 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3599 /* Check if we reached the limit and the last char is not \n.
3600 * Watch out for the last line without the terminating '\n'!
3601 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003602 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3603 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003605 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606 }
3607
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003608 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003609 newarg = 1;
3610 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611 if (*line == '#' || *line == '\n' || *line == '\r') {
3612 /* end of string, end of loop */
3613 *line = 0;
3614 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003616 newarg = 1;
3617 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003618 } else if (*line == '[') {
3619 if (ssl_b) {
3620 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3621 cfgerr = 1;
3622 break;
3623 }
3624 if (!arg) {
3625 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3626 cfgerr = 1;
3627 break;
3628 }
3629 ssl_b = arg;
3630 newarg = 1;
3631 *line = 0;
3632 } else if (*line == ']') {
3633 if (ssl_e) {
3634 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003635 cfgerr = 1;
3636 break;
3637 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003638 if (!ssl_b) {
3639 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3640 cfgerr = 1;
3641 break;
3642 }
3643 ssl_e = arg;
3644 newarg = 1;
3645 *line = 0;
3646 } else if (newarg) {
3647 if (arg == MAX_CRT_ARGS) {
3648 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3649 cfgerr = 1;
3650 break;
3651 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003652 newarg = 0;
3653 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003654 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003655 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003656 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003657 if (cfgerr)
3658 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003659 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003660
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003661 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003662 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003663 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003664
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003665 crt_path = args[0];
3666 if (*crt_path != '/' && global_ssl.crt_base) {
3667 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3668 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3669 crt_path, linenum, file);
3670 cfgerr = 1;
3671 break;
3672 }
3673 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3674 crt_path = path;
3675 }
3676
3677 ssl_conf = calloc(1, sizeof *ssl_conf);
3678 cur_arg = ssl_b ? ssl_b : 1;
3679 while (cur_arg < ssl_e) {
3680 newarg = 0;
3681 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3682 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3683 newarg = 1;
3684 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3685 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3686 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3687 args[cur_arg], linenum, file);
3688 cfgerr = 1;
3689 }
3690 cur_arg += 1 + ssl_bind_kws[i].skip;
3691 break;
3692 }
3693 }
3694 if (!cfgerr && !newarg) {
3695 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3696 args[cur_arg], linenum, file);
3697 cfgerr = 1;
3698 break;
3699 }
3700 }
3701 if (cfgerr) {
3702 ssl_sock_free_ssl_conf(ssl_conf);
3703 free(ssl_conf);
3704 ssl_conf = NULL;
3705 break;
3706 }
3707
3708 if (stat(crt_path, &buf) == 0) {
3709 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3710 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003711 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003712 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3713 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003714 }
3715
Willy Tarreauad1731d2013-04-02 17:35:58 +02003716 if (cfgerr) {
3717 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003718 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003719 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003720 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003721 fclose(f);
3722 return cfgerr;
3723}
3724
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003725/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003726static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003727ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003728{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003729 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003730 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003731 SSL_OP_ALL | /* all known workarounds for bugs */
3732 SSL_OP_NO_SSLv2 |
3733 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003734 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003735 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003736 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003737 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003738 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003739 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003740 SSL_MODE_ENABLE_PARTIAL_WRITE |
3741 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003742 SSL_MODE_RELEASE_BUFFERS |
3743 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003744 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003745 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003746 int flags = MC_SSL_O_ALL;
3747 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003748
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003749 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003750 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003751
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003752 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003753 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3754 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3755 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003756 else
3757 flags = conf_ssl_methods->flags;
3758
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003759 min = conf_ssl_methods->min;
3760 max = conf_ssl_methods->max;
3761 /* start with TLSv10 to remove SSLv3 per default */
3762 if (!min && (!max || max >= CONF_TLSV10))
3763 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003764 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003765 if (min)
3766 flags |= (methodVersions[min].flag - 1);
3767 if (max)
3768 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003769 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003770 min = max = CONF_TLSV_NONE;
3771 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003772 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003773 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003774 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003775 if (min) {
3776 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003777 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3778 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3779 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3780 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003781 hole = 0;
3782 }
3783 max = i;
3784 }
3785 else {
3786 min = max = i;
3787 }
3788 }
3789 else {
3790 if (min)
3791 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003792 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003793 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003794 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3795 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003796 cfgerr += 1;
3797 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003798 /* save real min/max in bind_conf */
3799 conf_ssl_methods->min = min;
3800 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003801
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003802#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003803 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003804 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003805 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003806 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003807 else
3808 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3809 if (flags & methodVersions[i].flag)
3810 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003811#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003812 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003813 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3814 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003815#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003816
3817 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3818 options |= SSL_OP_NO_TICKET;
3819 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3820 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3821 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003822
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003823#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003824 if (global_ssl.async)
3825 mode |= SSL_MODE_ASYNC;
3826#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003827 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003828 if (global_ssl.life_time)
3829 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003830
3831#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3832#ifdef OPENSSL_IS_BORINGSSL
3833 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3834 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003835#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3836 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3837 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003838#else
3839 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003840#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003841 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003842#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003843 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003844}
3845
William Lallemand4f45bb92017-10-30 20:08:51 +01003846
3847static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3848{
3849 if (first == block) {
3850 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3851 if (first->len > 0)
3852 sh_ssl_sess_tree_delete(sh_ssl_sess);
3853 }
3854}
3855
3856/* return first block from sh_ssl_sess */
3857static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3858{
3859 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3860
3861}
3862
3863/* store a session into the cache
3864 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3865 * data: asn1 encoded session
3866 * data_len: asn1 encoded session length
3867 * Returns 1 id session was stored (else 0)
3868 */
3869static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3870{
3871 struct shared_block *first;
3872 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3873
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003874 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003875 if (!first) {
3876 /* Could not retrieve enough free blocks to store that session */
3877 return 0;
3878 }
3879
3880 /* STORE the key in the first elem */
3881 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3882 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3883 first->len = sizeof(struct sh_ssl_sess_hdr);
3884
3885 /* it returns the already existing node
3886 or current node if none, never returns null */
3887 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3888 if (oldsh_ssl_sess != sh_ssl_sess) {
3889 /* NOTE: Row couldn't be in use because we lock read & write function */
3890 /* release the reserved row */
3891 shctx_row_dec_hot(ssl_shctx, first);
3892 /* replace the previous session already in the tree */
3893 sh_ssl_sess = oldsh_ssl_sess;
3894 /* ignore the previous session data, only use the header */
3895 first = sh_ssl_sess_first_block(sh_ssl_sess);
3896 shctx_row_inc_hot(ssl_shctx, first);
3897 first->len = sizeof(struct sh_ssl_sess_hdr);
3898 }
3899
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003900 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003901 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003902 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003903 }
3904
3905 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003906
3907 return 1;
3908}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003909
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003910/* SSL callback used when a new session is created while connecting to a server */
3911static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3912{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003913 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003914 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003915
Willy Tarreau07d94e42018-09-20 10:57:52 +02003916 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003917
Olivier Houcharde6060c52017-11-16 17:42:52 +01003918 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3919 int len;
3920 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003921
Olivier Houcharde6060c52017-11-16 17:42:52 +01003922 len = i2d_SSL_SESSION(sess, NULL);
3923 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3924 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3925 } else {
3926 free(s->ssl_ctx.reused_sess[tid].ptr);
3927 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3928 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3929 }
3930 if (s->ssl_ctx.reused_sess[tid].ptr) {
3931 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3932 &ptr);
3933 }
3934 } else {
3935 free(s->ssl_ctx.reused_sess[tid].ptr);
3936 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3937 }
3938
3939 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003940}
3941
Olivier Houcharde6060c52017-11-16 17:42:52 +01003942
William Lallemanded0b5ad2017-10-30 19:36:36 +01003943/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003944int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003945{
3946 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3947 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3948 unsigned char *p;
3949 int data_len;
3950 unsigned int sid_length, sid_ctx_length;
3951 const unsigned char *sid_data;
3952 const unsigned char *sid_ctx_data;
3953
3954 /* Session id is already stored in to key and session id is known
3955 * so we dont store it to keep size.
3956 */
3957
3958 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3959 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3960 SSL_SESSION_set1_id(sess, sid_data, 0);
3961 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3962
3963 /* check if buffer is large enough for the ASN1 encoded session */
3964 data_len = i2d_SSL_SESSION(sess, NULL);
3965 if (data_len > SHSESS_MAX_DATA_LEN)
3966 goto err;
3967
3968 p = encsess;
3969
3970 /* process ASN1 session encoding before the lock */
3971 i2d_SSL_SESSION(sess, &p);
3972
3973 memcpy(encid, sid_data, sid_length);
3974 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3975 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3976
William Lallemanda3c77cf2017-10-30 23:44:40 +01003977 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003978 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003979 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003980 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003981err:
3982 /* reset original length values */
3983 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3984 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3985
3986 return 0; /* do not increment session reference count */
3987}
3988
3989/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003990SSL_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 +01003991{
William Lallemand4f45bb92017-10-30 20:08:51 +01003992 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003993 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3994 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003995 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003996 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003997
3998 global.shctx_lookups++;
3999
4000 /* allow the session to be freed automatically by openssl */
4001 *do_copy = 0;
4002
4003 /* tree key is zeros padded sessionid */
4004 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4005 memcpy(tmpkey, key, key_len);
4006 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4007 key = tmpkey;
4008 }
4009
4010 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004011 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004012
4013 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004014 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4015 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004016 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004017 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004018 global.shctx_misses++;
4019 return NULL;
4020 }
4021
William Lallemand4f45bb92017-10-30 20:08:51 +01004022 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4023 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004024
William Lallemand4f45bb92017-10-30 20:08:51 +01004025 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 +01004026
William Lallemanda3c77cf2017-10-30 23:44:40 +01004027 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004028
4029 /* decode ASN1 session */
4030 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004031 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004032 /* Reset session id and session id contenxt */
4033 if (sess) {
4034 SSL_SESSION_set1_id(sess, key, key_len);
4035 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4036 }
4037
4038 return sess;
4039}
4040
William Lallemand4f45bb92017-10-30 20:08:51 +01004041
William Lallemanded0b5ad2017-10-30 19:36:36 +01004042/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004043void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004044{
William Lallemand4f45bb92017-10-30 20:08:51 +01004045 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004046 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4047 unsigned int sid_length;
4048 const unsigned char *sid_data;
4049 (void)ctx;
4050
4051 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4052 /* tree key is zeros padded sessionid */
4053 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4054 memcpy(tmpkey, sid_data, sid_length);
4055 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4056 sid_data = tmpkey;
4057 }
4058
William Lallemanda3c77cf2017-10-30 23:44:40 +01004059 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004060
4061 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004062 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4063 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004064 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004065 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004066 }
4067
4068 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004069 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004070}
4071
4072/* Set session cache mode to server and disable openssl internal cache.
4073 * Set shared cache callbacks on an ssl context.
4074 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004075void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004076{
4077 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4078
4079 if (!ssl_shctx) {
4080 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4081 return;
4082 }
4083
4084 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4085 SSL_SESS_CACHE_NO_INTERNAL |
4086 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4087
4088 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004089 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4090 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4091 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004092}
4093
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004094int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4095{
4096 struct proxy *curproxy = bind_conf->frontend;
4097 int cfgerr = 0;
4098 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004099 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004100 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004101#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4102 const char *conf_ciphersuites;
4103#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004104 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004105
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004106 if (ssl_conf) {
4107 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4108 int i, min, max;
4109 int flags = MC_SSL_O_ALL;
4110
4111 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004112 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4113 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004114 if (min)
4115 flags |= (methodVersions[min].flag - 1);
4116 if (max)
4117 flags |= ~((methodVersions[max].flag << 1) - 1);
4118 min = max = CONF_TLSV_NONE;
4119 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4120 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4121 if (min)
4122 max = i;
4123 else
4124 min = max = i;
4125 }
4126 /* save real min/max */
4127 conf_ssl_methods->min = min;
4128 conf_ssl_methods->max = max;
4129 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004130 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4131 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004132 cfgerr += 1;
4133 }
4134 }
4135
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004136 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004137 case SSL_SOCK_VERIFY_NONE:
4138 verify = SSL_VERIFY_NONE;
4139 break;
4140 case SSL_SOCK_VERIFY_OPTIONAL:
4141 verify = SSL_VERIFY_PEER;
4142 break;
4143 case SSL_SOCK_VERIFY_REQUIRED:
4144 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4145 break;
4146 }
4147 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4148 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004149 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4150 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4151 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004152 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004153 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004154 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4155 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004156 cfgerr++;
4157 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004158 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4159 /* set CA names for client cert request, function returns void */
4160 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4161 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004162 }
Emeric Brun850efd52014-01-29 12:24:34 +01004163 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004164 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4165 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004166 cfgerr++;
4167 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004168#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004169 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004170 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4171
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004172 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004173 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4174 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004175 cfgerr++;
4176 }
Emeric Brun561e5742012-10-02 15:20:55 +02004177 else {
4178 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4179 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004180 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004181#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004182 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004183 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004184#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004185 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004186 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004187 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4188 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004189 cfgerr++;
4190 }
4191 }
4192#endif
4193
William Lallemand4f45bb92017-10-30 20:08:51 +01004194 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004195 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4196 if (conf_ciphers &&
4197 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004198 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4199 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004200 cfgerr++;
4201 }
4202
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004203#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4204 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4205 if (conf_ciphersuites &&
4206 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4207 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4208 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4209 cfgerr++;
4210 }
4211#endif
4212
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004213#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004214 /* If tune.ssl.default-dh-param has not been set,
4215 neither has ssl-default-dh-file and no static DH
4216 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004217 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004218 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004219 (ssl_dh_ptr_index == -1 ||
4220 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004221 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4222 const SSL_CIPHER * cipher = NULL;
4223 char cipher_description[128];
4224 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4225 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4226 which is not ephemeral DH. */
4227 const char dhe_description[] = " Kx=DH ";
4228 const char dhe_export_description[] = " Kx=DH(";
4229 int idx = 0;
4230 int dhe_found = 0;
4231 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004232
Remi Gacogne23d5d372014-10-10 17:04:26 +02004233 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004234
Remi Gacogne23d5d372014-10-10 17:04:26 +02004235 if (ssl) {
4236 ciphers = SSL_get_ciphers(ssl);
4237
4238 if (ciphers) {
4239 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4240 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4241 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4242 if (strstr(cipher_description, dhe_description) != NULL ||
4243 strstr(cipher_description, dhe_export_description) != NULL) {
4244 dhe_found = 1;
4245 break;
4246 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004247 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004248 }
4249 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004250 SSL_free(ssl);
4251 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004252 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004253
Lukas Tribus90132722014-08-18 00:56:33 +02004254 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004255 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 +02004256 }
4257
Willy Tarreauef934602016-12-22 23:12:01 +01004258 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004259 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004260
Willy Tarreauef934602016-12-22 23:12:01 +01004261 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004262 if (local_dh_1024 == NULL) {
4263 local_dh_1024 = ssl_get_dh_1024();
4264 }
Willy Tarreauef934602016-12-22 23:12:01 +01004265 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004266 if (local_dh_2048 == NULL) {
4267 local_dh_2048 = ssl_get_dh_2048();
4268 }
Willy Tarreauef934602016-12-22 23:12:01 +01004269 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004270 if (local_dh_4096 == NULL) {
4271 local_dh_4096 = ssl_get_dh_4096();
4272 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004273 }
4274 }
4275 }
4276#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004277
Emeric Brunfc0421f2012-09-07 17:30:07 +02004278 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004279#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004280 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004281#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004282
Bernard Spil13c53f82018-02-15 13:34:58 +01004283#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004284 ssl_conf_cur = NULL;
4285 if (ssl_conf && ssl_conf->npn_str)
4286 ssl_conf_cur = ssl_conf;
4287 else if (bind_conf->ssl_conf.npn_str)
4288 ssl_conf_cur = &bind_conf->ssl_conf;
4289 if (ssl_conf_cur)
4290 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004291#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004292#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004293 ssl_conf_cur = NULL;
4294 if (ssl_conf && ssl_conf->alpn_str)
4295 ssl_conf_cur = ssl_conf;
4296 else if (bind_conf->ssl_conf.alpn_str)
4297 ssl_conf_cur = &bind_conf->ssl_conf;
4298 if (ssl_conf_cur)
4299 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004300#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004301#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4302 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4303 if (conf_curves) {
4304 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004305 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4306 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004307 cfgerr++;
4308 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004309#if defined(SSL_CTX_set_ecdh_auto)
4310 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4311#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004312 }
4313#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004314#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004315 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004316 int i;
4317 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004318#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004319 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004320 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4321 NULL);
4322
4323 if (ecdhe == NULL) {
4324 SSL_CTX_set_dh_auto(ctx, 1);
4325 return cfgerr;
4326 }
4327#else
4328 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4329 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4330 ECDHE_DEFAULT_CURVE);
4331#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004332
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004333 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004334 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004335 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4336 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004337 cfgerr++;
4338 }
4339 else {
4340 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4341 EC_KEY_free(ecdh);
4342 }
4343 }
4344#endif
4345
Emeric Brunfc0421f2012-09-07 17:30:07 +02004346 return cfgerr;
4347}
4348
Evan Broderbe554312013-06-27 00:05:25 -07004349static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4350{
4351 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4352 size_t prefixlen, suffixlen;
4353
4354 /* Trivial case */
4355 if (strcmp(pattern, hostname) == 0)
4356 return 1;
4357
Evan Broderbe554312013-06-27 00:05:25 -07004358 /* The rest of this logic is based on RFC 6125, section 6.4.3
4359 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4360
Emeric Bruna848dae2013-10-08 11:27:28 +02004361 pattern_wildcard = NULL;
4362 pattern_left_label_end = pattern;
4363 while (*pattern_left_label_end != '.') {
4364 switch (*pattern_left_label_end) {
4365 case 0:
4366 /* End of label not found */
4367 return 0;
4368 case '*':
4369 /* If there is more than one wildcards */
4370 if (pattern_wildcard)
4371 return 0;
4372 pattern_wildcard = pattern_left_label_end;
4373 break;
4374 }
4375 pattern_left_label_end++;
4376 }
4377
4378 /* If it's not trivial and there is no wildcard, it can't
4379 * match */
4380 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004381 return 0;
4382
4383 /* Make sure all labels match except the leftmost */
4384 hostname_left_label_end = strchr(hostname, '.');
4385 if (!hostname_left_label_end
4386 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4387 return 0;
4388
4389 /* Make sure the leftmost label of the hostname is long enough
4390 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004391 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004392 return 0;
4393
4394 /* Finally compare the string on either side of the
4395 * wildcard */
4396 prefixlen = pattern_wildcard - pattern;
4397 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004398 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4399 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004400 return 0;
4401
4402 return 1;
4403}
4404
4405static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4406{
4407 SSL *ssl;
4408 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004409 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004410 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004411
4412 int depth;
4413 X509 *cert;
4414 STACK_OF(GENERAL_NAME) *alt_names;
4415 int i;
4416 X509_NAME *cert_subject;
4417 char *str;
4418
4419 if (ok == 0)
4420 return ok;
4421
4422 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004423 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004424
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004425 /* We're checking if the provided hostnames match the desired one. The
4426 * desired hostname comes from the SNI we presented if any, or if not
4427 * provided then it may have been explicitly stated using a "verifyhost"
4428 * directive. If neither is set, we don't care about the name so the
4429 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004430 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004431 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004432 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004433 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004434 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004435 if (!servername)
4436 return ok;
4437 }
Evan Broderbe554312013-06-27 00:05:25 -07004438
4439 /* We only need to verify the CN on the actual server cert,
4440 * not the indirect CAs */
4441 depth = X509_STORE_CTX_get_error_depth(ctx);
4442 if (depth != 0)
4443 return ok;
4444
4445 /* At this point, the cert is *not* OK unless we can find a
4446 * hostname match */
4447 ok = 0;
4448
4449 cert = X509_STORE_CTX_get_current_cert(ctx);
4450 /* It seems like this might happen if verify peer isn't set */
4451 if (!cert)
4452 return ok;
4453
4454 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4455 if (alt_names) {
4456 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4457 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4458 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004459#if OPENSSL_VERSION_NUMBER < 0x00907000L
4460 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4461#else
Evan Broderbe554312013-06-27 00:05:25 -07004462 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004463#endif
Evan Broderbe554312013-06-27 00:05:25 -07004464 ok = ssl_sock_srv_hostcheck(str, servername);
4465 OPENSSL_free(str);
4466 }
4467 }
4468 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004469 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004470 }
4471
4472 cert_subject = X509_get_subject_name(cert);
4473 i = -1;
4474 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4475 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004476 ASN1_STRING *value;
4477 value = X509_NAME_ENTRY_get_data(entry);
4478 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004479 ok = ssl_sock_srv_hostcheck(str, servername);
4480 OPENSSL_free(str);
4481 }
4482 }
4483
Willy Tarreau71d058c2017-07-26 20:09:56 +02004484 /* report the mismatch and indicate if SNI was used or not */
4485 if (!ok && !conn->err_code)
4486 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004487 return ok;
4488}
4489
Emeric Brun94324a42012-10-11 14:00:19 +02004490/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004491int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004492{
Willy Tarreau03209342016-12-22 17:08:28 +01004493 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004494 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004495 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004496 SSL_OP_ALL | /* all known workarounds for bugs */
4497 SSL_OP_NO_SSLv2 |
4498 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004499 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004500 SSL_MODE_ENABLE_PARTIAL_WRITE |
4501 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004502 SSL_MODE_RELEASE_BUFFERS |
4503 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004504 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004505 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004506 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004507 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004508 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004509
Thierry Fournier383085f2013-01-24 14:15:43 +01004510 /* Make sure openssl opens /dev/urandom before the chroot */
4511 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004512 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004513 cfgerr++;
4514 }
4515
Willy Tarreaufce03112015-01-15 21:32:40 +01004516 /* Automatic memory computations need to know we use SSL there */
4517 global.ssl_used_backend = 1;
4518
4519 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004520 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004521 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004522 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4523 curproxy->id, srv->id,
4524 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004525 cfgerr++;
4526 return cfgerr;
4527 }
4528 }
Emeric Brun94324a42012-10-11 14:00:19 +02004529 if (srv->use_ssl)
4530 srv->xprt = &ssl_sock;
4531 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004532 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004533
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004534 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004535 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004536 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4537 proxy_type_str(curproxy), curproxy->id,
4538 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004539 cfgerr++;
4540 return cfgerr;
4541 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004542
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004543 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004544 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4545 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4546 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004547 else
4548 flags = conf_ssl_methods->flags;
4549
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004550 /* Real min and max should be determinate with configuration and openssl's capabilities */
4551 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004552 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004553 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004554 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004555
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004556 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004557 min = max = CONF_TLSV_NONE;
4558 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004559 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004560 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004561 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004562 if (min) {
4563 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004564 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4565 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4566 proxy_type_str(curproxy), curproxy->id, srv->id,
4567 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004568 hole = 0;
4569 }
4570 max = i;
4571 }
4572 else {
4573 min = max = i;
4574 }
4575 }
4576 else {
4577 if (min)
4578 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004579 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004580 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004581 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4582 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004583 cfgerr += 1;
4584 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004585
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004586#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004587 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004588 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004589 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004590 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004591 else
4592 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4593 if (flags & methodVersions[i].flag)
4594 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004595#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004596 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004597 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4598 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004599#endif
4600
4601 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4602 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004603 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004604
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004605#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004606 if (global_ssl.async)
4607 mode |= SSL_MODE_ASYNC;
4608#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004609 SSL_CTX_set_mode(ctx, mode);
4610 srv->ssl_ctx.ctx = ctx;
4611
Emeric Bruna7aa3092012-10-26 12:58:00 +02004612 if (srv->ssl_ctx.client_crt) {
4613 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 +01004614 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4615 proxy_type_str(curproxy), curproxy->id,
4616 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004617 cfgerr++;
4618 }
4619 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 +01004620 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4621 proxy_type_str(curproxy), curproxy->id,
4622 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004623 cfgerr++;
4624 }
4625 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004626 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4627 proxy_type_str(curproxy), curproxy->id,
4628 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004629 cfgerr++;
4630 }
4631 }
Emeric Brun94324a42012-10-11 14:00:19 +02004632
Emeric Brun850efd52014-01-29 12:24:34 +01004633 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4634 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004635 switch (srv->ssl_ctx.verify) {
4636 case SSL_SOCK_VERIFY_NONE:
4637 verify = SSL_VERIFY_NONE;
4638 break;
4639 case SSL_SOCK_VERIFY_REQUIRED:
4640 verify = SSL_VERIFY_PEER;
4641 break;
4642 }
Evan Broderbe554312013-06-27 00:05:25 -07004643 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004644 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004645 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004646 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004647 if (srv->ssl_ctx.ca_file) {
4648 /* load CAfile to verify */
4649 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004650 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4651 curproxy->id, srv->id,
4652 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004653 cfgerr++;
4654 }
4655 }
Emeric Brun850efd52014-01-29 12:24:34 +01004656 else {
4657 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004658 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",
4659 curproxy->id, srv->id,
4660 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004661 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004662 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4663 curproxy->id, srv->id,
4664 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004665 cfgerr++;
4666 }
Emeric Brunef42d922012-10-11 16:11:36 +02004667#ifdef X509_V_FLAG_CRL_CHECK
4668 if (srv->ssl_ctx.crl_file) {
4669 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4670
4671 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004672 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4673 curproxy->id, srv->id,
4674 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004675 cfgerr++;
4676 }
4677 else {
4678 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4679 }
4680 }
4681#endif
4682 }
4683
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004684 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4685 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4686 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004687 if (srv->ssl_ctx.ciphers &&
4688 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004689 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4690 curproxy->id, srv->id,
4691 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004692 cfgerr++;
4693 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004694
4695#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4696 if (srv->ssl_ctx.ciphersuites &&
4697 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4698 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4699 curproxy->id, srv->id,
4700 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4701 cfgerr++;
4702 }
4703#endif
Emeric Brun94324a42012-10-11 14:00:19 +02004704
4705 return cfgerr;
4706}
4707
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004708/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004709 * be NULL, in which case nothing is done. Returns the number of errors
4710 * encountered.
4711 */
Willy Tarreau03209342016-12-22 17:08:28 +01004712int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004713{
4714 struct ebmb_node *node;
4715 struct sni_ctx *sni;
4716 int err = 0;
4717
Willy Tarreaufce03112015-01-15 21:32:40 +01004718 /* Automatic memory computations need to know we use SSL there */
4719 global.ssl_used_frontend = 1;
4720
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004721 /* Make sure openssl opens /dev/urandom before the chroot */
4722 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004723 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004724 err++;
4725 }
4726 /* Create initial_ctx used to start the ssl connection before do switchctx */
4727 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004728 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004729 /* It should not be necessary to call this function, but it's
4730 necessary first to check and move all initialisation related
4731 to initial_ctx in ssl_sock_initial_ctx. */
4732 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4733 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004734 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004735 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004736
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004737 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004738 while (node) {
4739 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004740 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4741 /* only initialize the CTX on its first occurrence and
4742 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004743 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004744 node = ebmb_next(node);
4745 }
4746
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004747 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004748 while (node) {
4749 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004750 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4751 /* only initialize the CTX on its first occurrence and
4752 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004753 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004754 node = ebmb_next(node);
4755 }
4756 return err;
4757}
4758
Willy Tarreau55d37912016-12-21 23:38:39 +01004759/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4760 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4761 * alerts are directly emitted since the rest of the stack does it below.
4762 */
4763int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4764{
4765 struct proxy *px = bind_conf->frontend;
4766 int alloc_ctx;
4767 int err;
4768
4769 if (!bind_conf->is_ssl) {
4770 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004771 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4772 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004773 }
4774 return 0;
4775 }
4776 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004777 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004778 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4779 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004780 }
4781 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004782 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4783 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004784 return -1;
4785 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004786 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004787 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004788 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004789 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004790 sizeof(*sh_ssl_sess_tree),
4791 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004792 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004793 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4794 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");
4795 else
4796 ha_alert("Unable to allocate SSL session cache.\n");
4797 return -1;
4798 }
4799 /* free block callback */
4800 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4801 /* init the root tree within the extra space */
4802 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4803 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004804 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004805 err = 0;
4806 /* initialize all certificate contexts */
4807 err += ssl_sock_prepare_all_ctx(bind_conf);
4808
4809 /* initialize CA variables if the certificates generation is enabled */
4810 err += ssl_sock_load_ca(bind_conf);
4811
4812 return -err;
4813}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004814
4815/* release ssl context allocated for servers. */
4816void ssl_sock_free_srv_ctx(struct server *srv)
4817{
4818 if (srv->ssl_ctx.ctx)
4819 SSL_CTX_free(srv->ssl_ctx.ctx);
4820}
4821
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004822/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004823 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4824 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004825void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004826{
4827 struct ebmb_node *node, *back;
4828 struct sni_ctx *sni;
4829
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004830 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004831 while (node) {
4832 sni = ebmb_entry(node, struct sni_ctx, name);
4833 back = ebmb_next(node);
4834 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004835 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004836 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004837 ssl_sock_free_ssl_conf(sni->conf);
4838 free(sni->conf);
4839 sni->conf = NULL;
4840 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004841 free(sni);
4842 node = back;
4843 }
4844
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004845 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004846 while (node) {
4847 sni = ebmb_entry(node, struct sni_ctx, name);
4848 back = ebmb_next(node);
4849 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004850 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004851 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004852 ssl_sock_free_ssl_conf(sni->conf);
4853 free(sni->conf);
4854 sni->conf = NULL;
4855 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004856 free(sni);
4857 node = back;
4858 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004859 SSL_CTX_free(bind_conf->initial_ctx);
4860 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004861 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004862 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004863}
4864
Willy Tarreau795cdab2016-12-22 17:30:54 +01004865/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4866void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4867{
4868 ssl_sock_free_ca(bind_conf);
4869 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004870 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004871 free(bind_conf->ca_sign_file);
4872 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004873 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004874 free(bind_conf->keys_ref->filename);
4875 free(bind_conf->keys_ref->tlskeys);
4876 LIST_DEL(&bind_conf->keys_ref->list);
4877 free(bind_conf->keys_ref);
4878 }
4879 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004880 bind_conf->ca_sign_pass = NULL;
4881 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004882}
4883
Christopher Faulet31af49d2015-06-09 17:29:50 +02004884/* Load CA cert file and private key used to generate certificates */
4885int
Willy Tarreau03209342016-12-22 17:08:28 +01004886ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004887{
Willy Tarreau03209342016-12-22 17:08:28 +01004888 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004889 FILE *fp;
4890 X509 *cacert = NULL;
4891 EVP_PKEY *capkey = NULL;
4892 int err = 0;
4893
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004894 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004895 return err;
4896
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004897#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004898 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004899 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004900 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004901 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004902 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004903 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004904#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004905
Christopher Faulet31af49d2015-06-09 17:29:50 +02004906 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004907 ha_alert("Proxy '%s': cannot enable certificate generation, "
4908 "no CA certificate File configured at [%s:%d].\n",
4909 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004910 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004911 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004912
4913 /* read in the CA certificate */
4914 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004915 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4916 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004917 goto load_error;
4918 }
4919 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004920 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4921 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004922 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004923 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004924 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004925 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004926 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4927 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004928 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004929 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004930
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004931 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004932 bind_conf->ca_sign_cert = cacert;
4933 bind_conf->ca_sign_pkey = capkey;
4934 return err;
4935
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004936 read_error:
4937 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004938 if (capkey) EVP_PKEY_free(capkey);
4939 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004940 load_error:
4941 bind_conf->generate_certs = 0;
4942 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004943 return err;
4944}
4945
4946/* Release CA cert and private key used to generate certificated */
4947void
4948ssl_sock_free_ca(struct bind_conf *bind_conf)
4949{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004950 if (bind_conf->ca_sign_pkey)
4951 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4952 if (bind_conf->ca_sign_cert)
4953 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004954 bind_conf->ca_sign_pkey = NULL;
4955 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004956}
4957
Emeric Brun46591952012-05-18 15:47:34 +02004958/*
4959 * This function is called if SSL * context is not yet allocated. The function
4960 * is designed to be called before any other data-layer operation and sets the
4961 * handshake flag on the connection. It is safe to call it multiple times.
4962 * It returns 0 on success and -1 in error case.
4963 */
4964static int ssl_sock_init(struct connection *conn)
4965{
4966 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004967 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004968 return 0;
4969
Willy Tarreau3c728722014-01-23 13:50:42 +01004970 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004971 return 0;
4972
Willy Tarreau20879a02012-12-03 16:32:10 +01004973 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4974 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004975 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004976 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004977
Emeric Brun46591952012-05-18 15:47:34 +02004978 /* If it is in client mode initiate SSL session
4979 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004980 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004981 int may_retry = 1;
4982
4983 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004984 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02004985 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004986 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004987 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004988 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004989 goto retry_connect;
4990 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004991 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004992 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004993 }
Emeric Brun46591952012-05-18 15:47:34 +02004994
Emeric Brun46591952012-05-18 15:47:34 +02004995 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004996 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004997 SSL_free(conn->xprt_ctx);
4998 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004999 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005000 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005001 goto retry_connect;
5002 }
Emeric Brun55476152014-11-12 17:35:37 +01005003 conn->err_code = CO_ER_SSL_NO_MEM;
5004 return -1;
5005 }
Emeric Brun46591952012-05-18 15:47:34 +02005006
Evan Broderbe554312013-06-27 00:05:25 -07005007 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005008 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005009 SSL_free(conn->xprt_ctx);
5010 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005011 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005012 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005013 goto retry_connect;
5014 }
Emeric Brun55476152014-11-12 17:35:37 +01005015 conn->err_code = CO_ER_SSL_NO_MEM;
5016 return -1;
5017 }
5018
5019 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005020 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5021 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5022 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5023 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005024 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005025 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5026 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005027 } else if (sess) {
5028 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005029 }
5030 }
Evan Broderbe554312013-06-27 00:05:25 -07005031
Emeric Brun46591952012-05-18 15:47:34 +02005032 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005033 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005034
Emeric Brun7ad43e72018-10-10 14:51:02 +02005035 HA_ATOMIC_ADD(&sslconns, 1);
5036 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005037 return 0;
5038 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005039 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005040 int may_retry = 1;
5041
5042 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005043 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005044 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005045 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005046 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005047 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005048 goto retry_accept;
5049 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005050 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005051 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005052 }
Emeric Brun46591952012-05-18 15:47:34 +02005053
Emeric Brun46591952012-05-18 15:47:34 +02005054 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005055 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005056 SSL_free(conn->xprt_ctx);
5057 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005058 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005059 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005060 goto retry_accept;
5061 }
Emeric Brun55476152014-11-12 17:35:37 +01005062 conn->err_code = CO_ER_SSL_NO_MEM;
5063 return -1;
5064 }
Emeric Brun46591952012-05-18 15:47:34 +02005065
Emeric Brune1f38db2012-09-03 20:36:47 +02005066 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005067 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005068 SSL_free(conn->xprt_ctx);
5069 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005070 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005071 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005072 goto retry_accept;
5073 }
Emeric Brun55476152014-11-12 17:35:37 +01005074 conn->err_code = CO_ER_SSL_NO_MEM;
5075 return -1;
5076 }
5077
5078 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005079
Emeric Brun46591952012-05-18 15:47:34 +02005080 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005081 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005082#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005083 conn->flags |= CO_FL_EARLY_SSL_HS;
5084#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005085
Emeric Brun7ad43e72018-10-10 14:51:02 +02005086 HA_ATOMIC_ADD(&sslconns, 1);
5087 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005088 return 0;
5089 }
5090 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005091 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005092 return -1;
5093}
5094
5095
5096/* This is the callback which is used when an SSL handshake is pending. It
5097 * updates the FD status if it wants some polling before being called again.
5098 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5099 * otherwise it returns non-zero and removes itself from the connection's
5100 * flags (the bit is provided in <flag> by the caller).
5101 */
5102int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5103{
5104 int ret;
5105
Willy Tarreau3c728722014-01-23 13:50:42 +01005106 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005107 return 0;
5108
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005109 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005110 goto out_error;
5111
Olivier Houchardc2aae742017-09-22 18:26:28 +02005112#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5113 /*
5114 * Check if we have early data. If we do, we have to read them
5115 * before SSL_do_handshake() is called, And there's no way to
5116 * detect early data, except to try to read them
5117 */
5118 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5119 size_t read_data;
5120
5121 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5122 1, &read_data);
5123 if (ret == SSL_READ_EARLY_DATA_ERROR)
5124 goto check_error;
5125 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5126 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5127 return 1;
5128 } else
5129 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5130 }
5131#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005132 /* If we use SSL_do_handshake to process a reneg initiated by
5133 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5134 * Usually SSL_write and SSL_read are used and process implicitly
5135 * the reneg handshake.
5136 * Here we use SSL_peek as a workaround for reneg.
5137 */
5138 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5139 char c;
5140
5141 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5142 if (ret <= 0) {
5143 /* handshake may have not been completed, let's find why */
5144 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005145
Emeric Brun674b7432012-11-08 19:21:55 +01005146 if (ret == SSL_ERROR_WANT_WRITE) {
5147 /* SSL handshake needs to write, L4 connection may not be ready */
5148 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005149 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005150 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005151 return 0;
5152 }
5153 else if (ret == SSL_ERROR_WANT_READ) {
5154 /* handshake may have been completed but we have
5155 * no more data to read.
5156 */
5157 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5158 ret = 1;
5159 goto reneg_ok;
5160 }
5161 /* SSL handshake needs to read, L4 connection is ready */
5162 if (conn->flags & CO_FL_WAIT_L4_CONN)
5163 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5164 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005165 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005166 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005167 return 0;
5168 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005169#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005170 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005171 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005172 return 0;
5173 }
5174#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005175 else if (ret == SSL_ERROR_SYSCALL) {
5176 /* if errno is null, then connection was successfully established */
5177 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5178 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005179 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005180#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005181 conn->err_code = CO_ER_SSL_HANDSHAKE;
5182#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005183 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005184#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005185 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5186 empty_handshake = state == TLS_ST_BEFORE;
5187#else
5188 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5189#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005190 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005191 if (!errno) {
5192 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5193 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5194 else
5195 conn->err_code = CO_ER_SSL_EMPTY;
5196 }
5197 else {
5198 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5199 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5200 else
5201 conn->err_code = CO_ER_SSL_ABORT;
5202 }
5203 }
5204 else {
5205 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5206 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005207 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005208 conn->err_code = CO_ER_SSL_HANDSHAKE;
5209 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005210#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005211 }
Emeric Brun674b7432012-11-08 19:21:55 +01005212 goto out_error;
5213 }
5214 else {
5215 /* Fail on all other handshake errors */
5216 /* Note: OpenSSL may leave unread bytes in the socket's
5217 * buffer, causing an RST to be emitted upon close() on
5218 * TCP sockets. We first try to drain possibly pending
5219 * data to avoid this as much as possible.
5220 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005221 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005222 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005223 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5224 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005225 goto out_error;
5226 }
5227 }
5228 /* read some data: consider handshake completed */
5229 goto reneg_ok;
5230 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005231 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005232check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005233 if (ret != 1) {
5234 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005235 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005236
5237 if (ret == SSL_ERROR_WANT_WRITE) {
5238 /* SSL handshake needs to write, L4 connection may not be ready */
5239 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005240 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005241 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005242 return 0;
5243 }
5244 else if (ret == SSL_ERROR_WANT_READ) {
5245 /* SSL handshake needs to read, L4 connection is ready */
5246 if (conn->flags & CO_FL_WAIT_L4_CONN)
5247 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5248 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005249 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005250 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005251 return 0;
5252 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005253#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005254 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005255 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005256 return 0;
5257 }
5258#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005259 else if (ret == SSL_ERROR_SYSCALL) {
5260 /* if errno is null, then connection was successfully established */
5261 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5262 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005263 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005264#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005265 conn->err_code = CO_ER_SSL_HANDSHAKE;
5266#else
5267 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005268#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005269 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5270 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005271#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005272 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005273#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005274 if (empty_handshake) {
5275 if (!errno) {
5276 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5277 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5278 else
5279 conn->err_code = CO_ER_SSL_EMPTY;
5280 }
5281 else {
5282 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5283 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5284 else
5285 conn->err_code = CO_ER_SSL_ABORT;
5286 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005287 }
5288 else {
5289 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5290 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5291 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005292 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005293 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005294#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005295 }
Willy Tarreau89230192012-09-28 20:22:13 +02005296 goto out_error;
5297 }
Emeric Brun46591952012-05-18 15:47:34 +02005298 else {
5299 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005300 /* Note: OpenSSL may leave unread bytes in the socket's
5301 * buffer, causing an RST to be emitted upon close() on
5302 * TCP sockets. We first try to drain possibly pending
5303 * data to avoid this as much as possible.
5304 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005305 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005306 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005307 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5308 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005309 goto out_error;
5310 }
5311 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005312#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5313 else {
5314 /*
5315 * If the server refused the early data, we have to send a
5316 * 425 to the client, as we no longer have the data to sent
5317 * them again.
5318 */
5319 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5320 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5321 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5322 goto out_error;
5323 }
5324 }
5325 }
5326#endif
5327
Emeric Brun46591952012-05-18 15:47:34 +02005328
Emeric Brun674b7432012-11-08 19:21:55 +01005329reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005330
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005331#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005332 /* ASYNC engine API doesn't support moving read/write
5333 * buffers. So we disable ASYNC mode right after
5334 * the handshake to avoid buffer oveflows.
5335 */
5336 if (global_ssl.async)
5337 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5338#endif
Emeric Brun46591952012-05-18 15:47:34 +02005339 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005340 if (!SSL_session_reused(conn->xprt_ctx)) {
5341 if (objt_server(conn->target)) {
5342 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5343 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5344 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005345 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005346 else {
5347 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5348 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5349 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5350 }
Emeric Brun46591952012-05-18 15:47:34 +02005351 }
5352
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005353#ifdef OPENSSL_IS_BORINGSSL
5354 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5355 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5356#endif
Emeric Brun46591952012-05-18 15:47:34 +02005357 /* The connection is now established at both layers, it's time to leave */
5358 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5359 return 1;
5360
5361 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005362 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005363 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005364 ERR_clear_error();
5365
Emeric Brun9fa89732012-10-04 17:09:56 +02005366 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005367 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5368 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5369 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005370 }
5371
Emeric Brun46591952012-05-18 15:47:34 +02005372 /* Fail on all other handshake errors */
5373 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005374 if (!conn->err_code)
5375 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005376 return 0;
5377}
5378
5379/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005380 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005381 * buffer wraps, in which case a second call may be performed. The connection's
5382 * flags are updated with whatever special event is detected (error, read0,
5383 * empty). The caller is responsible for taking care of those events and
5384 * avoiding the call if inappropriate. The function does not call the
5385 * connection's polling update function, so the caller is responsible for this.
5386 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005387static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005388{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005389 ssize_t ret;
5390 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005391
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005392 conn_refresh_polling_flags(conn);
5393
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005394 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005395 goto out_error;
5396
5397 if (conn->flags & CO_FL_HANDSHAKE)
5398 /* a handshake was requested */
5399 return 0;
5400
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005401 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005402
5403 /* read the largest possible block. For this, we perform only one call
5404 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5405 * in which case we accept to do it once again. A new attempt is made on
5406 * EINTR too.
5407 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005408 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005409 int need_out = 0;
5410
Willy Tarreau591d4452018-06-15 17:21:00 +02005411 try = b_contig_space(buf);
5412 if (!try)
5413 break;
5414
Willy Tarreauabf08d92014-01-14 11:31:27 +01005415 if (try > count)
5416 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005417
Olivier Houchardc2aae742017-09-22 18:26:28 +02005418 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5419 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005420 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005421 done++;
5422 try--;
5423 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005424 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005425 conn->tmp_early_data = -1;
5426 continue;
5427 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005428
Olivier Houchardc2aae742017-09-22 18:26:28 +02005429#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5430 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5431 size_t read_length;
5432
5433 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005434 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005435 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5436 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005437 conn->flags |= CO_FL_EARLY_DATA;
5438 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5439 ret == SSL_READ_EARLY_DATA_FINISH) {
5440 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5441 /*
5442 * We're done reading the early data,
5443 * let's make the handshake
5444 */
5445 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5446 conn->flags |= CO_FL_SSL_WAIT_HS;
5447 need_out = 1;
5448 if (read_length == 0)
5449 break;
5450 }
5451 ret = read_length;
5452 }
5453 } else
5454#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005455 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005456#ifdef OPENSSL_IS_BORINGSSL
5457 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5458 if (SSL_in_early_data(conn->xprt_ctx)) {
5459 if (ret > 0)
5460 conn->flags |= CO_FL_EARLY_DATA;
5461 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005462 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005463 }
5464 }
5465#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005466 if (conn->flags & CO_FL_ERROR) {
5467 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005468 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005469 }
Emeric Brun46591952012-05-18 15:47:34 +02005470 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005471 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005472 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005473 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005474 }
Emeric Brun46591952012-05-18 15:47:34 +02005475 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005476 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005477 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005478 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005479 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005480 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005481#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005482 /* Async mode can be re-enabled, because we're leaving data state.*/
5483 if (global_ssl.async)
5484 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5485#endif
Emeric Brun46591952012-05-18 15:47:34 +02005486 break;
5487 }
5488 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005489 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5490 /* handshake is running, and it may need to re-enable read */
5491 conn->flags |= CO_FL_SSL_WAIT_HS;
5492 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005493#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005494 /* Async mode can be re-enabled, because we're leaving data state.*/
5495 if (global_ssl.async)
5496 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5497#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005498 break;
5499 }
Emeric Brun46591952012-05-18 15:47:34 +02005500 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005501 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005502 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005503 } else if (ret == SSL_ERROR_ZERO_RETURN)
5504 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005505 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5506 * stack before shutting down the connection for
5507 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005508 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5509 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005510 /* otherwise it's a real error */
5511 goto out_error;
5512 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005513 if (need_out)
5514 break;
Emeric Brun46591952012-05-18 15:47:34 +02005515 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005516 leave:
5517 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005518 return done;
5519
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005520 clear_ssl_error:
5521 /* Clear openssl global errors stack */
5522 ssl_sock_dump_errors(conn);
5523 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005524 read0:
5525 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005526 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005527
Emeric Brun46591952012-05-18 15:47:34 +02005528 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005529 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005530 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005531 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005532 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005533 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005534}
5535
5536
Willy Tarreau787db9a2018-06-14 18:31:46 +02005537/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5538 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5539 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005540 * Only one call to send() is performed, unless the buffer wraps, in which case
5541 * a second call may be performed. The connection's flags are updated with
5542 * whatever special event is detected (error, empty). The caller is responsible
5543 * for taking care of those events and avoiding the call if inappropriate. The
5544 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005545 * is responsible for this. The buffer's output is not adjusted, it's up to the
5546 * caller to take care of this. It's up to the caller to update the buffer's
5547 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005548 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005549static 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 +02005550{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005551 ssize_t ret;
5552 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005553
5554 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005555 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005556
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005557 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005558 goto out_error;
5559
5560 if (conn->flags & CO_FL_HANDSHAKE)
5561 /* a handshake was requested */
5562 return 0;
5563
5564 /* send the largest possible block. For this we perform only one call
5565 * to send() unless the buffer wraps and we exactly fill the first hunk,
5566 * in which case we accept to do it once again.
5567 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005568 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005569#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5570 size_t written_data;
5571#endif
5572
Willy Tarreau787db9a2018-06-14 18:31:46 +02005573 try = b_contig_data(buf, done);
5574 if (try > count)
5575 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005576
Willy Tarreau7bed9452014-02-02 02:00:24 +01005577 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005578 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005579 global_ssl.max_record && try > global_ssl.max_record) {
5580 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005581 }
5582 else {
5583 /* we need to keep the information about the fact that
5584 * we're not limiting the upcoming send(), because if it
5585 * fails, we'll have to retry with at least as many data.
5586 */
5587 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5588 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005589
Olivier Houchardc2aae742017-09-22 18:26:28 +02005590#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5591 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5592 unsigned int max_early;
5593
Olivier Houchard522eea72017-11-03 16:27:47 +01005594 if (objt_listener(conn->target))
5595 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5596 else {
5597 if (SSL_get0_session(conn->xprt_ctx))
5598 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5599 else
5600 max_early = 0;
5601 }
5602
Olivier Houchard90084a12017-11-23 18:21:29 +01005603 if (try + conn->sent_early_data > max_early) {
5604 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005605 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005606 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5607 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005608 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005609 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005610 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005611 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005612 if (ret == 1) {
5613 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005614 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005615 if (objt_server(conn->target)) {
5616 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5617 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5618 }
5619
Olivier Houchardc2aae742017-09-22 18:26:28 +02005620 }
5621
5622 } else
5623#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005624 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005625
Emeric Brune1f38db2012-09-03 20:36:47 +02005626 if (conn->flags & CO_FL_ERROR) {
5627 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005628 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005629 }
Emeric Brun46591952012-05-18 15:47:34 +02005630 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005631 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005632 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005633 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005634 }
5635 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005636 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005637
Emeric Brun46591952012-05-18 15:47:34 +02005638 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005639 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5640 /* handshake is running, and it may need to re-enable write */
5641 conn->flags |= CO_FL_SSL_WAIT_HS;
5642 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005643#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005644 /* Async mode can be re-enabled, because we're leaving data state.*/
5645 if (global_ssl.async)
5646 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5647#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005648 break;
5649 }
Emeric Brun46591952012-05-18 15:47:34 +02005650 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005651 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005652 break;
5653 }
5654 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005655 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005656 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005657 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005658#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005659 /* Async mode can be re-enabled, because we're leaving data state.*/
5660 if (global_ssl.async)
5661 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5662#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005663 break;
5664 }
Emeric Brun46591952012-05-18 15:47:34 +02005665 goto out_error;
5666 }
5667 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005668 leave:
5669 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005670 return done;
5671
5672 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005673 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005674 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005675 ERR_clear_error();
5676
Emeric Brun46591952012-05-18 15:47:34 +02005677 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005678 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005679}
5680
Emeric Brun46591952012-05-18 15:47:34 +02005681static void ssl_sock_close(struct connection *conn) {
5682
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005683 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005684#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005685 if (global_ssl.async) {
5686 OSSL_ASYNC_FD all_fd[32], afd;
5687 size_t num_all_fds = 0;
5688 int i;
5689
5690 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5691 if (num_all_fds > 32) {
5692 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5693 return;
5694 }
5695
5696 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5697
5698 /* If an async job is pending, we must try to
5699 to catch the end using polling before calling
5700 SSL_free */
5701 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5702 for (i=0 ; i < num_all_fds ; i++) {
5703 /* switch on an handler designed to
5704 * handle the SSL_free
5705 */
5706 afd = all_fd[i];
5707 fdtab[afd].iocb = ssl_async_fd_free;
5708 fdtab[afd].owner = conn->xprt_ctx;
5709 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005710 /* To ensure that the fd cache won't be used
5711 * and we'll catch a real RD event.
5712 */
5713 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005714 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005715 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005716 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005717 return;
5718 }
Emeric Brun3854e012017-05-17 20:42:48 +02005719 /* Else we can remove the fds from the fdtab
5720 * and call SSL_free.
5721 * note: we do a fd_remove and not a delete
5722 * because the fd is owned by the engine.
5723 * the engine is responsible to close
5724 */
5725 for (i=0 ; i < num_all_fds ; i++)
5726 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005727 }
5728#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005729 SSL_free(conn->xprt_ctx);
5730 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005731 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005732 }
Emeric Brun46591952012-05-18 15:47:34 +02005733}
5734
5735/* This function tries to perform a clean shutdown on an SSL connection, and in
5736 * any case, flags the connection as reusable if no handshake was in progress.
5737 */
5738static void ssl_sock_shutw(struct connection *conn, int clean)
5739{
5740 if (conn->flags & CO_FL_HANDSHAKE)
5741 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005742 if (!clean)
5743 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005744 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005745 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005746 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005747 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005748 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005749 ERR_clear_error();
5750 }
Emeric Brun46591952012-05-18 15:47:34 +02005751}
5752
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005753/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005754int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005755{
5756 struct pkey_info *pkinfo;
5757 int bits = 0;
5758 int sig = TLSEXT_signature_anonymous;
5759 int len = -1;
5760
5761 if (!ssl_sock_is_ssl(conn))
5762 return 0;
5763
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005764 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005765 if (pkinfo) {
5766 sig = pkinfo->sig;
5767 bits = pkinfo->bits;
5768 } else {
5769 /* multicert and generated cert have no pkey info */
5770 X509 *crt;
5771 EVP_PKEY *pkey;
5772 crt = SSL_get_certificate(conn->xprt_ctx);
5773 if (!crt)
5774 return 0;
5775 pkey = X509_get_pubkey(crt);
5776 if (pkey) {
5777 bits = EVP_PKEY_bits(pkey);
5778 switch(EVP_PKEY_base_id(pkey)) {
5779 case EVP_PKEY_RSA:
5780 sig = TLSEXT_signature_rsa;
5781 break;
5782 case EVP_PKEY_EC:
5783 sig = TLSEXT_signature_ecdsa;
5784 break;
5785 case EVP_PKEY_DSA:
5786 sig = TLSEXT_signature_dsa;
5787 break;
5788 }
5789 EVP_PKEY_free(pkey);
5790 }
5791 }
5792
5793 switch(sig) {
5794 case TLSEXT_signature_rsa:
5795 len = chunk_printf(out, "RSA%d", bits);
5796 break;
5797 case TLSEXT_signature_ecdsa:
5798 len = chunk_printf(out, "EC%d", bits);
5799 break;
5800 case TLSEXT_signature_dsa:
5801 len = chunk_printf(out, "DSA%d", bits);
5802 break;
5803 default:
5804 return 0;
5805 }
5806 if (len < 0)
5807 return 0;
5808 return 1;
5809}
5810
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005811/* used for ppv2 cert signature (can be used for logging) */
5812const char *ssl_sock_get_cert_sig(struct connection *conn)
5813{
5814 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5815 X509 *crt;
5816
5817 if (!ssl_sock_is_ssl(conn))
5818 return NULL;
5819 crt = SSL_get_certificate(conn->xprt_ctx);
5820 if (!crt)
5821 return NULL;
5822 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5823 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5824}
5825
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005826/* used for ppv2 authority */
5827const char *ssl_sock_get_sni(struct connection *conn)
5828{
5829#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5830 if (!ssl_sock_is_ssl(conn))
5831 return NULL;
5832 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5833#else
5834 return 0;
5835#endif
5836}
5837
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005838/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005839const char *ssl_sock_get_cipher_name(struct connection *conn)
5840{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005841 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005842 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005843
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005844 return SSL_get_cipher_name(conn->xprt_ctx);
5845}
5846
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005847/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005848const char *ssl_sock_get_proto_version(struct connection *conn)
5849{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005850 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005851 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005852
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005853 return SSL_get_version(conn->xprt_ctx);
5854}
5855
Willy Tarreau8d598402012-10-22 17:58:39 +02005856/* Extract a serial from a cert, and copy it to a chunk.
5857 * Returns 1 if serial is found and copied, 0 if no serial found and
5858 * -1 if output is not large enough.
5859 */
5860static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005861ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005862{
5863 ASN1_INTEGER *serial;
5864
5865 serial = X509_get_serialNumber(crt);
5866 if (!serial)
5867 return 0;
5868
5869 if (out->size < serial->length)
5870 return -1;
5871
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005872 memcpy(out->area, serial->data, serial->length);
5873 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005874 return 1;
5875}
5876
Emeric Brun43e79582014-10-29 19:03:26 +01005877/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005878 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5879 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005880 */
5881static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005882ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005883{
5884 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005885 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005886
5887 len =i2d_X509(crt, NULL);
5888 if (len <= 0)
5889 return 1;
5890
5891 if (out->size < len)
5892 return -1;
5893
5894 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005895 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005896 return 1;
5897}
5898
Emeric Brunce5ad802012-10-22 14:11:22 +02005899
Willy Tarreau83061a82018-07-13 11:56:34 +02005900/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005901 * Returns 1 if serial is found and copied, 0 if no valid time found
5902 * and -1 if output is not large enough.
5903 */
5904static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005905ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005906{
5907 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5908 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5909
5910 if (gentm->length < 12)
5911 return 0;
5912 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5913 return 0;
5914 if (out->size < gentm->length-2)
5915 return -1;
5916
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005917 memcpy(out->area, gentm->data+2, gentm->length-2);
5918 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005919 return 1;
5920 }
5921 else if (tm->type == V_ASN1_UTCTIME) {
5922 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5923
5924 if (utctm->length < 10)
5925 return 0;
5926 if (utctm->data[0] >= 0x35)
5927 return 0;
5928 if (out->size < utctm->length)
5929 return -1;
5930
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005931 memcpy(out->area, utctm->data, utctm->length);
5932 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005933 return 1;
5934 }
5935
5936 return 0;
5937}
5938
Emeric Brun87855892012-10-17 17:39:35 +02005939/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5940 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5941 */
5942static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005943ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5944 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005945{
5946 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005947 ASN1_OBJECT *obj;
5948 ASN1_STRING *data;
5949 const unsigned char *data_ptr;
5950 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005951 int i, j, n;
5952 int cur = 0;
5953 const char *s;
5954 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005955 int name_count;
5956
5957 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005958
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005959 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005960 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005961 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005962 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005963 else
5964 j = i;
5965
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005966 ne = X509_NAME_get_entry(a, j);
5967 obj = X509_NAME_ENTRY_get_object(ne);
5968 data = X509_NAME_ENTRY_get_data(ne);
5969 data_ptr = ASN1_STRING_get0_data(data);
5970 data_len = ASN1_STRING_length(data);
5971 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005972 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005973 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005974 s = tmp;
5975 }
5976
5977 if (chunk_strcasecmp(entry, s) != 0)
5978 continue;
5979
5980 if (pos < 0)
5981 cur--;
5982 else
5983 cur++;
5984
5985 if (cur != pos)
5986 continue;
5987
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005988 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005989 return -1;
5990
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005991 memcpy(out->area, data_ptr, data_len);
5992 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005993 return 1;
5994 }
5995
5996 return 0;
5997
5998}
5999
6000/* Extract and format full DN from a X509_NAME and copy result into a chunk
6001 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6002 */
6003static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006004ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006005{
6006 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006007 ASN1_OBJECT *obj;
6008 ASN1_STRING *data;
6009 const unsigned char *data_ptr;
6010 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006011 int i, n, ln;
6012 int l = 0;
6013 const char *s;
6014 char *p;
6015 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006016 int name_count;
6017
6018
6019 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006020
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006021 out->data = 0;
6022 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006023 for (i = 0; i < name_count; i++) {
6024 ne = X509_NAME_get_entry(a, i);
6025 obj = X509_NAME_ENTRY_get_object(ne);
6026 data = X509_NAME_ENTRY_get_data(ne);
6027 data_ptr = ASN1_STRING_get0_data(data);
6028 data_len = ASN1_STRING_length(data);
6029 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006030 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006031 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006032 s = tmp;
6033 }
6034 ln = strlen(s);
6035
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006036 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006037 if (l > out->size)
6038 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006039 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006040
6041 *(p++)='/';
6042 memcpy(p, s, ln);
6043 p += ln;
6044 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006045 memcpy(p, data_ptr, data_len);
6046 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006047 }
6048
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006049 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006050 return 0;
6051
6052 return 1;
6053}
6054
Willy Tarreau119a4082016-12-22 21:58:38 +01006055/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6056 * to disable SNI.
6057 */
Willy Tarreau63076412015-07-10 11:33:32 +02006058void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6059{
6060#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006061 char *prev_name;
6062
Willy Tarreau63076412015-07-10 11:33:32 +02006063 if (!ssl_sock_is_ssl(conn))
6064 return;
6065
Willy Tarreau119a4082016-12-22 21:58:38 +01006066 /* if the SNI changes, we must destroy the reusable context so that a
6067 * new connection will present a new SNI. As an optimization we could
6068 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6069 * server.
6070 */
6071 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6072 if ((!prev_name && hostname) ||
6073 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6074 SSL_set_session(conn->xprt_ctx, NULL);
6075
Willy Tarreau63076412015-07-10 11:33:32 +02006076 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6077#endif
6078}
6079
Emeric Brun0abf8362014-06-24 18:26:41 +02006080/* Extract peer certificate's common name into the chunk dest
6081 * Returns
6082 * the len of the extracted common name
6083 * or 0 if no CN found in DN
6084 * or -1 on error case (i.e. no peer certificate)
6085 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006086int ssl_sock_get_remote_common_name(struct connection *conn,
6087 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006088{
6089 X509 *crt = NULL;
6090 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006091 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006092 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006093 .area = (char *)&find_cn,
6094 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006095 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006096 int result = -1;
David Safb76832014-05-08 23:42:08 -04006097
6098 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006099 goto out;
David Safb76832014-05-08 23:42:08 -04006100
6101 /* SSL_get_peer_certificate, it increase X509 * ref count */
6102 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6103 if (!crt)
6104 goto out;
6105
6106 name = X509_get_subject_name(crt);
6107 if (!name)
6108 goto out;
David Safb76832014-05-08 23:42:08 -04006109
Emeric Brun0abf8362014-06-24 18:26:41 +02006110 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6111out:
David Safb76832014-05-08 23:42:08 -04006112 if (crt)
6113 X509_free(crt);
6114
6115 return result;
6116}
6117
Dave McCowan328fb582014-07-30 10:39:13 -04006118/* returns 1 if client passed a certificate for this session, 0 if not */
6119int ssl_sock_get_cert_used_sess(struct connection *conn)
6120{
6121 X509 *crt = NULL;
6122
6123 if (!ssl_sock_is_ssl(conn))
6124 return 0;
6125
6126 /* SSL_get_peer_certificate, it increase X509 * ref count */
6127 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6128 if (!crt)
6129 return 0;
6130
6131 X509_free(crt);
6132 return 1;
6133}
6134
6135/* returns 1 if client passed a certificate for this connection, 0 if not */
6136int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006137{
6138 if (!ssl_sock_is_ssl(conn))
6139 return 0;
6140
6141 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6142}
6143
6144/* returns result from SSL verify */
6145unsigned int ssl_sock_get_verify_result(struct connection *conn)
6146{
6147 if (!ssl_sock_is_ssl(conn))
6148 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6149
6150 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6151}
6152
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006153/* Returns the application layer protocol name in <str> and <len> when known.
6154 * Zero is returned if the protocol name was not found, otherwise non-zero is
6155 * returned. The string is allocated in the SSL context and doesn't have to be
6156 * freed by the caller. NPN is also checked if available since older versions
6157 * of openssl (1.0.1) which are more common in field only support this one.
6158 */
6159static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6160{
6161 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6162 return 0;
6163
6164 *str = NULL;
6165
6166#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6167 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6168 if (*str)
6169 return 1;
6170#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006171#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006172 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6173 if (*str)
6174 return 1;
6175#endif
6176 return 0;
6177}
6178
Willy Tarreau7875d092012-09-10 08:20:03 +02006179/***** Below are some sample fetching functions for ACL/patterns *****/
6180
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006181static int
6182smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6183{
6184 struct connection *conn;
6185
6186 conn = objt_conn(smp->sess->origin);
6187 if (!conn || conn->xprt != &ssl_sock)
6188 return 0;
6189
6190 smp->flags = 0;
6191 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006192 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6193 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006194
6195 return 1;
6196}
6197
Emeric Brune64aef12012-09-21 13:15:06 +02006198/* boolean, returns true if client cert was present */
6199static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006200smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006201{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006202 struct connection *conn;
6203
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006204 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006205 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006206 return 0;
6207
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006208 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006209 smp->flags |= SMP_F_MAY_CHANGE;
6210 return 0;
6211 }
6212
6213 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006214 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006215 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006216
6217 return 1;
6218}
6219
Emeric Brun43e79582014-10-29 19:03:26 +01006220/* binary, returns a certificate in a binary chunk (der/raw).
6221 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6222 * should be use.
6223 */
6224static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006225smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006226{
6227 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6228 X509 *crt = NULL;
6229 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006230 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006231 struct connection *conn;
6232
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006233 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006234 if (!conn || conn->xprt != &ssl_sock)
6235 return 0;
6236
6237 if (!(conn->flags & CO_FL_CONNECTED)) {
6238 smp->flags |= SMP_F_MAY_CHANGE;
6239 return 0;
6240 }
6241
6242 if (cert_peer)
6243 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6244 else
6245 crt = SSL_get_certificate(conn->xprt_ctx);
6246
6247 if (!crt)
6248 goto out;
6249
6250 smp_trash = get_trash_chunk();
6251 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6252 goto out;
6253
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006254 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006255 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006256 ret = 1;
6257out:
6258 /* SSL_get_peer_certificate, it increase X509 * ref count */
6259 if (cert_peer && crt)
6260 X509_free(crt);
6261 return ret;
6262}
6263
Emeric Brunba841a12014-04-30 17:05:08 +02006264/* binary, returns serial of certificate in a binary chunk.
6265 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6266 * should be use.
6267 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006268static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006269smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006270{
Emeric Brunba841a12014-04-30 17:05:08 +02006271 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006272 X509 *crt = NULL;
6273 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006274 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006275 struct connection *conn;
6276
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006277 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006278 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006279 return 0;
6280
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006281 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006282 smp->flags |= SMP_F_MAY_CHANGE;
6283 return 0;
6284 }
6285
Emeric Brunba841a12014-04-30 17:05:08 +02006286 if (cert_peer)
6287 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6288 else
6289 crt = SSL_get_certificate(conn->xprt_ctx);
6290
Willy Tarreau8d598402012-10-22 17:58:39 +02006291 if (!crt)
6292 goto out;
6293
Willy Tarreau47ca5452012-12-23 20:22:19 +01006294 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006295 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6296 goto out;
6297
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006298 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006299 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006300 ret = 1;
6301out:
Emeric Brunba841a12014-04-30 17:05:08 +02006302 /* SSL_get_peer_certificate, it increase X509 * ref count */
6303 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006304 X509_free(crt);
6305 return ret;
6306}
Emeric Brune64aef12012-09-21 13:15:06 +02006307
Emeric Brunba841a12014-04-30 17:05:08 +02006308/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6309 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6310 * should be use.
6311 */
James Votha051b4a2013-05-14 20:37:59 +02006312static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006313smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006314{
Emeric Brunba841a12014-04-30 17:05:08 +02006315 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006316 X509 *crt = NULL;
6317 const EVP_MD *digest;
6318 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006319 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006320 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006321
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006322 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006323 if (!conn || conn->xprt != &ssl_sock)
6324 return 0;
6325
6326 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006327 smp->flags |= SMP_F_MAY_CHANGE;
6328 return 0;
6329 }
6330
Emeric Brunba841a12014-04-30 17:05:08 +02006331 if (cert_peer)
6332 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6333 else
6334 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006335 if (!crt)
6336 goto out;
6337
6338 smp_trash = get_trash_chunk();
6339 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006340 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6341 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006342
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006343 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006344 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006345 ret = 1;
6346out:
Emeric Brunba841a12014-04-30 17:05:08 +02006347 /* SSL_get_peer_certificate, it increase X509 * ref count */
6348 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006349 X509_free(crt);
6350 return ret;
6351}
6352
Emeric Brunba841a12014-04-30 17:05:08 +02006353/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6354 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6355 * should be use.
6356 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006357static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006358smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006359{
Emeric Brunba841a12014-04-30 17:05:08 +02006360 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006361 X509 *crt = NULL;
6362 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006363 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006364 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006365
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006366 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006367 if (!conn || conn->xprt != &ssl_sock)
6368 return 0;
6369
6370 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006371 smp->flags |= SMP_F_MAY_CHANGE;
6372 return 0;
6373 }
6374
Emeric Brunba841a12014-04-30 17:05:08 +02006375 if (cert_peer)
6376 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6377 else
6378 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006379 if (!crt)
6380 goto out;
6381
Willy Tarreau47ca5452012-12-23 20:22:19 +01006382 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006383 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6384 goto out;
6385
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006386 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006387 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006388 ret = 1;
6389out:
Emeric Brunba841a12014-04-30 17:05:08 +02006390 /* SSL_get_peer_certificate, it increase X509 * ref count */
6391 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006392 X509_free(crt);
6393 return ret;
6394}
6395
Emeric Brunba841a12014-04-30 17:05:08 +02006396/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6397 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6398 * should be use.
6399 */
Emeric Brun87855892012-10-17 17:39:35 +02006400static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006401smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006402{
Emeric Brunba841a12014-04-30 17:05:08 +02006403 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006404 X509 *crt = NULL;
6405 X509_NAME *name;
6406 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006407 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006408 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006409
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006410 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006411 if (!conn || conn->xprt != &ssl_sock)
6412 return 0;
6413
6414 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006415 smp->flags |= SMP_F_MAY_CHANGE;
6416 return 0;
6417 }
6418
Emeric Brunba841a12014-04-30 17:05:08 +02006419 if (cert_peer)
6420 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6421 else
6422 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006423 if (!crt)
6424 goto out;
6425
6426 name = X509_get_issuer_name(crt);
6427 if (!name)
6428 goto out;
6429
Willy Tarreau47ca5452012-12-23 20:22:19 +01006430 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006431 if (args && args[0].type == ARGT_STR) {
6432 int pos = 1;
6433
6434 if (args[1].type == ARGT_SINT)
6435 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006436
6437 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6438 goto out;
6439 }
6440 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6441 goto out;
6442
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006443 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006444 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006445 ret = 1;
6446out:
Emeric Brunba841a12014-04-30 17:05:08 +02006447 /* SSL_get_peer_certificate, it increase X509 * ref count */
6448 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006449 X509_free(crt);
6450 return ret;
6451}
6452
Emeric Brunba841a12014-04-30 17:05:08 +02006453/* string, returns notbefore date in ASN1_UTCTIME format.
6454 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6455 * should be use.
6456 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006457static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006458smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006459{
Emeric Brunba841a12014-04-30 17:05:08 +02006460 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006461 X509 *crt = NULL;
6462 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006463 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006464 struct connection *conn;
6465
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006466 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006467 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006468 return 0;
6469
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006470 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006471 smp->flags |= SMP_F_MAY_CHANGE;
6472 return 0;
6473 }
6474
Emeric Brunba841a12014-04-30 17:05:08 +02006475 if (cert_peer)
6476 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6477 else
6478 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006479 if (!crt)
6480 goto out;
6481
Willy Tarreau47ca5452012-12-23 20:22:19 +01006482 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006483 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6484 goto out;
6485
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006486 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006487 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006488 ret = 1;
6489out:
Emeric Brunba841a12014-04-30 17:05:08 +02006490 /* SSL_get_peer_certificate, it increase X509 * ref count */
6491 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006492 X509_free(crt);
6493 return ret;
6494}
6495
Emeric Brunba841a12014-04-30 17:05:08 +02006496/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6497 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6498 * should be use.
6499 */
Emeric Brun87855892012-10-17 17:39:35 +02006500static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006501smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006502{
Emeric Brunba841a12014-04-30 17:05:08 +02006503 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006504 X509 *crt = NULL;
6505 X509_NAME *name;
6506 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006507 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006508 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006509
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006510 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006511 if (!conn || conn->xprt != &ssl_sock)
6512 return 0;
6513
6514 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006515 smp->flags |= SMP_F_MAY_CHANGE;
6516 return 0;
6517 }
6518
Emeric Brunba841a12014-04-30 17:05:08 +02006519 if (cert_peer)
6520 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6521 else
6522 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006523 if (!crt)
6524 goto out;
6525
6526 name = X509_get_subject_name(crt);
6527 if (!name)
6528 goto out;
6529
Willy Tarreau47ca5452012-12-23 20:22:19 +01006530 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006531 if (args && args[0].type == ARGT_STR) {
6532 int pos = 1;
6533
6534 if (args[1].type == ARGT_SINT)
6535 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006536
6537 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6538 goto out;
6539 }
6540 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6541 goto out;
6542
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006543 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006544 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006545 ret = 1;
6546out:
Emeric Brunba841a12014-04-30 17:05:08 +02006547 /* SSL_get_peer_certificate, it increase X509 * ref count */
6548 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006549 X509_free(crt);
6550 return ret;
6551}
Emeric Brun9143d372012-12-20 15:44:16 +01006552
6553/* integer, returns true if current session use a client certificate */
6554static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006555smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006556{
6557 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006558 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006559
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006560 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006561 if (!conn || conn->xprt != &ssl_sock)
6562 return 0;
6563
6564 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006565 smp->flags |= SMP_F_MAY_CHANGE;
6566 return 0;
6567 }
6568
6569 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006570 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006571 if (crt) {
6572 X509_free(crt);
6573 }
6574
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006575 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006576 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006577 return 1;
6578}
6579
Emeric Brunba841a12014-04-30 17:05:08 +02006580/* integer, returns the certificate version
6581 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6582 * should be use.
6583 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006584static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006585smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006586{
Emeric Brunba841a12014-04-30 17:05:08 +02006587 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006588 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006589 struct connection *conn;
6590
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006591 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006592 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006593 return 0;
6594
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006595 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006596 smp->flags |= SMP_F_MAY_CHANGE;
6597 return 0;
6598 }
6599
Emeric Brunba841a12014-04-30 17:05:08 +02006600 if (cert_peer)
6601 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6602 else
6603 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006604 if (!crt)
6605 return 0;
6606
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006607 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006608 /* SSL_get_peer_certificate increase X509 * ref count */
6609 if (cert_peer)
6610 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006611 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006612
6613 return 1;
6614}
6615
Emeric Brunba841a12014-04-30 17:05:08 +02006616/* string, returns the certificate's signature algorithm.
6617 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6618 * should be use.
6619 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006620static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006621smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006622{
Emeric Brunba841a12014-04-30 17:05:08 +02006623 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006624 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006625 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006626 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006627 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006628
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006629 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006630 if (!conn || conn->xprt != &ssl_sock)
6631 return 0;
6632
6633 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006634 smp->flags |= SMP_F_MAY_CHANGE;
6635 return 0;
6636 }
6637
Emeric Brunba841a12014-04-30 17:05:08 +02006638 if (cert_peer)
6639 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6640 else
6641 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006642 if (!crt)
6643 return 0;
6644
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006645 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6646 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006647
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006648 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6649 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006650 /* SSL_get_peer_certificate increase X509 * ref count */
6651 if (cert_peer)
6652 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006653 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006654 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006655
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006656 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006657 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006658 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006659 /* SSL_get_peer_certificate increase X509 * ref count */
6660 if (cert_peer)
6661 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006662
6663 return 1;
6664}
6665
Emeric Brunba841a12014-04-30 17:05:08 +02006666/* string, returns the certificate's key algorithm.
6667 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6668 * should be use.
6669 */
Emeric Brun521a0112012-10-22 12:22:55 +02006670static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006671smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006672{
Emeric Brunba841a12014-04-30 17:05:08 +02006673 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006674 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006675 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006676 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006677 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006678
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006679 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006680 if (!conn || conn->xprt != &ssl_sock)
6681 return 0;
6682
6683 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006684 smp->flags |= SMP_F_MAY_CHANGE;
6685 return 0;
6686 }
6687
Emeric Brunba841a12014-04-30 17:05:08 +02006688 if (cert_peer)
6689 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6690 else
6691 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006692 if (!crt)
6693 return 0;
6694
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006695 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6696 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006697
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006698 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6699 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006700 /* SSL_get_peer_certificate increase X509 * ref count */
6701 if (cert_peer)
6702 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006703 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006704 }
Emeric Brun521a0112012-10-22 12:22:55 +02006705
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006706 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006707 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006708 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006709 if (cert_peer)
6710 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006711
6712 return 1;
6713}
6714
Emeric Brun645ae792014-04-30 14:21:06 +02006715/* boolean, returns true if front conn. transport layer is SSL.
6716 * This function is also usable on backend conn if the fetch keyword 5th
6717 * char is 'b'.
6718 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006719static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006720smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006721{
Emeric Bruneb8def92018-02-19 15:59:48 +01006722 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6723 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006724
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006725 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006726 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006727 return 1;
6728}
6729
Emeric Brun2525b6b2012-10-18 15:59:43 +02006730/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006731static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006732smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006733{
6734#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006735 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006736
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006737 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006738 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006739 conn->xprt_ctx &&
6740 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006741 return 1;
6742#else
6743 return 0;
6744#endif
6745}
6746
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006747/* boolean, returns true if client session has been resumed.
6748 * This function is also usable on backend conn if the fetch keyword 5th
6749 * char is 'b'.
6750 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006751static int
6752smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6753{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006754 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6755 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6756
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006757
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006758 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006759 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006760 conn->xprt_ctx &&
6761 SSL_session_reused(conn->xprt_ctx);
6762 return 1;
6763}
6764
Emeric Brun645ae792014-04-30 14:21:06 +02006765/* string, returns the used cipher if front conn. transport layer is SSL.
6766 * This function is also usable on backend conn if the fetch keyword 5th
6767 * char is 'b'.
6768 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006769static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006770smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006771{
Emeric Bruneb8def92018-02-19 15:59:48 +01006772 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6773 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006774
Willy Tarreaube508f12016-03-10 11:47:01 +01006775 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006776 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006777 return 0;
6778
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006779 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6780 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006781 return 0;
6782
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006783 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006784 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006785 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006786
6787 return 1;
6788}
6789
Emeric Brun645ae792014-04-30 14:21:06 +02006790/* integer, returns the algoritm's keysize if front conn. transport layer
6791 * is SSL.
6792 * This function is also usable on backend conn if the fetch keyword 5th
6793 * char is 'b'.
6794 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006795static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006796smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006797{
Emeric Bruneb8def92018-02-19 15:59:48 +01006798 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6799 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006800 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006801
Emeric Brun589fcad2012-10-16 14:13:26 +02006802 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006803 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006804 return 0;
6805
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006806 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006807 return 0;
6808
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006809 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006810 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006811
6812 return 1;
6813}
6814
Emeric Brun645ae792014-04-30 14:21:06 +02006815/* integer, returns the used keysize if front conn. transport layer is SSL.
6816 * This function is also usable on backend conn if the fetch keyword 5th
6817 * char is 'b'.
6818 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006819static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006820smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006821{
Emeric Bruneb8def92018-02-19 15:59:48 +01006822 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6823 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006824
Emeric Brun589fcad2012-10-16 14:13:26 +02006825 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006826 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6827 return 0;
6828
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006829 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6830 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006831 return 0;
6832
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006833 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006834
6835 return 1;
6836}
6837
Bernard Spil13c53f82018-02-15 13:34:58 +01006838#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006839static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006840smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006841{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006842 struct connection *conn;
6843
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006844 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006845 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006846
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006847 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006848 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6849 return 0;
6850
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006851 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006852 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006853 (const unsigned char **)&smp->data.u.str.area,
6854 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006855
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006856 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006857 return 0;
6858
6859 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006860}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006861#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006862
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006863#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006864static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006865smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006866{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006867 struct connection *conn;
6868
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006869 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006870 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006871
Willy Tarreaue26bf052015-05-12 10:30:12 +02006872 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006873 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006874 return 0;
6875
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006876 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006877 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006878 (const unsigned char **)&smp->data.u.str.area,
6879 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006880
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006881 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006882 return 0;
6883
6884 return 1;
6885}
6886#endif
6887
Emeric Brun645ae792014-04-30 14:21:06 +02006888/* string, returns the used protocol if front conn. transport layer is SSL.
6889 * This function is also usable on backend conn if the fetch keyword 5th
6890 * char is 'b'.
6891 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006892static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006893smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006894{
Emeric Bruneb8def92018-02-19 15:59:48 +01006895 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6896 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006897
Emeric Brun589fcad2012-10-16 14:13:26 +02006898 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6900 return 0;
6901
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006902 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6903 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006904 return 0;
6905
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006906 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006907 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006908 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006909
6910 return 1;
6911}
6912
Willy Tarreau87b09662015-04-03 00:22:06 +02006913/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006914 * This function is also usable on backend conn if the fetch keyword 5th
6915 * char is 'b'.
6916 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006917#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006918static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006919smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006920{
Emeric Bruneb8def92018-02-19 15:59:48 +01006921 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6922 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006923 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006924
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006925 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006926 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006927
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006928 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6929 return 0;
6930
Willy Tarreau192252e2015-04-04 01:47:55 +02006931 ssl_sess = SSL_get_session(conn->xprt_ctx);
6932 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006933 return 0;
6934
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006935 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6936 (unsigned int *)&smp->data.u.str.data);
6937 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006938 return 0;
6939
6940 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006941}
Patrick Hemmer41966772018-04-28 19:15:48 -04006942#endif
6943
Emeric Brunfe68f682012-10-16 14:59:28 +02006944
Patrick Hemmere0275472018-04-28 19:15:51 -04006945#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6946static int
6947smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6948{
6949 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6950 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6951 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006952 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006953
6954 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6955 return 0;
6956
6957 ssl_sess = SSL_get_session(conn->xprt_ctx);
6958 if (!ssl_sess)
6959 return 0;
6960
6961 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006962 data->data = SSL_SESSION_get_master_key(ssl_sess,
6963 (unsigned char *) data->area,
6964 data->size);
6965 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04006966 return 0;
6967
6968 smp->flags = 0;
6969 smp->data.type = SMP_T_BIN;
6970 smp->data.u.str = *data;
6971
6972 return 1;
6973}
6974#endif
6975
Patrick Hemmer41966772018-04-28 19:15:48 -04006976#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02006977static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006978smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006979{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006980 struct connection *conn;
6981
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006982 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006983 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006984
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006985 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006986 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6987 return 0;
6988
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006989 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6990 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006991 return 0;
6992
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006993 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02006994 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02006995}
Patrick Hemmer41966772018-04-28 19:15:48 -04006996#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02006997
David Sc1ad52e2014-04-08 18:48:47 -04006998static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006999smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7000{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007001 struct connection *conn;
7002 struct ssl_capture *capture;
7003
7004 conn = objt_conn(smp->sess->origin);
7005 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7006 return 0;
7007
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007008 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007009 if (!capture)
7010 return 0;
7011
7012 smp->flags = SMP_F_CONST;
7013 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007014 smp->data.u.str.area = capture->ciphersuite;
7015 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007016 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007017}
7018
7019static int
7020smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7021{
Willy Tarreau83061a82018-07-13 11:56:34 +02007022 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007023
7024 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7025 return 0;
7026
7027 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007028 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007029 smp->data.type = SMP_T_BIN;
7030 smp->data.u.str = *data;
7031 return 1;
7032}
7033
7034static int
7035smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7036{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007037 struct connection *conn;
7038 struct ssl_capture *capture;
7039
7040 conn = objt_conn(smp->sess->origin);
7041 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7042 return 0;
7043
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007044 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007045 if (!capture)
7046 return 0;
7047
7048 smp->data.type = SMP_T_SINT;
7049 smp->data.u.sint = capture->xxh64;
7050 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007051}
7052
7053static int
7054smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7055{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007056#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007057 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007058 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007059
7060 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7061 return 0;
7062
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007063 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007064 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007065 const char *str;
7066 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007067 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007068 uint16_t id = (bin[0] << 8) | bin[1];
7069#if defined(OPENSSL_IS_BORINGSSL)
7070 cipher = SSL_get_cipher_by_value(id);
7071#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007072 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007073 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7074#endif
7075 str = SSL_CIPHER_get_name(cipher);
7076 if (!str || strcmp(str, "(NONE)") == 0)
7077 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007078 else
7079 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7080 }
7081 smp->data.type = SMP_T_STR;
7082 smp->data.u.str = *data;
7083 return 1;
7084#else
7085 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7086#endif
7087}
7088
Patrick Hemmer41966772018-04-28 19:15:48 -04007089#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007090static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007091smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007092{
Emeric Bruneb8def92018-02-19 15:59:48 +01007093 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7094 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007095 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007096 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007097
7098 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007099 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7100 return 0;
7101
7102 if (!(conn->flags & CO_FL_CONNECTED)) {
7103 smp->flags |= SMP_F_MAY_CHANGE;
7104 return 0;
7105 }
7106
7107 finished_trash = get_trash_chunk();
7108 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007109 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7110 finished_trash->area,
7111 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007112 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007113 finished_len = SSL_get_finished(conn->xprt_ctx,
7114 finished_trash->area,
7115 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007116
7117 if (!finished_len)
7118 return 0;
7119
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007120 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007121 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007122 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007123
7124 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007125}
Patrick Hemmer41966772018-04-28 19:15:48 -04007126#endif
David Sc1ad52e2014-04-08 18:48:47 -04007127
Emeric Brun2525b6b2012-10-18 15:59:43 +02007128/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007129static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007130smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007131{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007132 struct connection *conn;
7133
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007134 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007135 if (!conn || conn->xprt != &ssl_sock)
7136 return 0;
7137
7138 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007139 smp->flags = SMP_F_MAY_CHANGE;
7140 return 0;
7141 }
7142
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007143 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007144 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007145 smp->flags = 0;
7146
7147 return 1;
7148}
7149
Emeric Brun2525b6b2012-10-18 15:59:43 +02007150/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007151static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007152smp_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 +02007153{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007154 struct connection *conn;
7155
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007156 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007157 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007158 return 0;
7159
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007160 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007161 smp->flags = SMP_F_MAY_CHANGE;
7162 return 0;
7163 }
7164
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007165 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007166 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007167 smp->flags = 0;
7168
7169 return 1;
7170}
7171
Emeric Brun2525b6b2012-10-18 15:59:43 +02007172/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007173static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007174smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007175{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007176 struct connection *conn;
7177
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007178 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007179 if (!conn || conn->xprt != &ssl_sock)
7180 return 0;
7181
7182 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007183 smp->flags = SMP_F_MAY_CHANGE;
7184 return 0;
7185 }
7186
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007187 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007188 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007189 smp->flags = 0;
7190
7191 return 1;
7192}
7193
Emeric Brun2525b6b2012-10-18 15:59:43 +02007194/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007195static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007196smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007197{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007198 struct connection *conn;
7199
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007200 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007201 if (!conn || conn->xprt != &ssl_sock)
7202 return 0;
7203
7204 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007205 smp->flags = SMP_F_MAY_CHANGE;
7206 return 0;
7207 }
7208
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007209 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007210 return 0;
7211
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007212 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007213 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007214 smp->flags = 0;
7215
7216 return 1;
7217}
7218
Emeric Brunfb510ea2012-10-05 12:00:26 +02007219/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007220static 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 +02007221{
7222 if (!*args[cur_arg + 1]) {
7223 if (err)
7224 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7225 return ERR_ALERT | ERR_FATAL;
7226 }
7227
Willy Tarreauef934602016-12-22 23:12:01 +01007228 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7229 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007230 else
7231 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007232
Emeric Brund94b3fe2012-09-20 18:23:56 +02007233 return 0;
7234}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007235static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7236{
7237 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7238}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007239
Christopher Faulet31af49d2015-06-09 17:29:50 +02007240/* parse the "ca-sign-file" bind keyword */
7241static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7242{
7243 if (!*args[cur_arg + 1]) {
7244 if (err)
7245 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7246 return ERR_ALERT | ERR_FATAL;
7247 }
7248
Willy Tarreauef934602016-12-22 23:12:01 +01007249 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7250 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007251 else
7252 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7253
7254 return 0;
7255}
7256
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007257/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007258static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7259{
7260 if (!*args[cur_arg + 1]) {
7261 if (err)
7262 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7263 return ERR_ALERT | ERR_FATAL;
7264 }
7265 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7266 return 0;
7267}
7268
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007269/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007270static 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 +02007271{
7272 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007273 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007274 return ERR_ALERT | ERR_FATAL;
7275 }
7276
Emeric Brun76d88952012-10-05 15:47:31 +02007277 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007278 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007279 return 0;
7280}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007281static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7282{
7283 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7284}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007285
7286#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7287/* parse the "ciphersuites" bind keyword */
7288static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7289{
7290 if (!*args[cur_arg + 1]) {
7291 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7292 return ERR_ALERT | ERR_FATAL;
7293 }
7294
7295 free(conf->ciphersuites);
7296 conf->ciphersuites = strdup(args[cur_arg + 1]);
7297 return 0;
7298}
7299static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7300{
7301 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7302}
7303#endif
7304
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007305/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007306static 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 +02007307{
Willy Tarreau38011032013-08-13 16:59:39 +02007308 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007309
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007310 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007311 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007312 return ERR_ALERT | ERR_FATAL;
7313 }
7314
Willy Tarreauef934602016-12-22 23:12:01 +01007315 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7316 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007317 memprintf(err, "'%s' : path too long", args[cur_arg]);
7318 return ERR_ALERT | ERR_FATAL;
7319 }
Willy Tarreauef934602016-12-22 23:12:01 +01007320 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007321 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007322 return ERR_ALERT | ERR_FATAL;
7323
7324 return 0;
7325 }
7326
Willy Tarreau03209342016-12-22 17:08:28 +01007327 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007328 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007329
7330 return 0;
7331}
7332
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007333/* parse the "crt-list" bind keyword */
7334static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7335{
7336 if (!*args[cur_arg + 1]) {
7337 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7338 return ERR_ALERT | ERR_FATAL;
7339 }
7340
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007341 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007342 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007343 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007344 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007345
7346 return 0;
7347}
7348
Emeric Brunfb510ea2012-10-05 12:00:26 +02007349/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007350static 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 +02007351{
Emeric Brun051cdab2012-10-02 19:25:50 +02007352#ifndef X509_V_FLAG_CRL_CHECK
7353 if (err)
7354 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7355 return ERR_ALERT | ERR_FATAL;
7356#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007357 if (!*args[cur_arg + 1]) {
7358 if (err)
7359 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7360 return ERR_ALERT | ERR_FATAL;
7361 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007362
Willy Tarreauef934602016-12-22 23:12:01 +01007363 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7364 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007365 else
7366 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007367
Emeric Brun2b58d042012-09-20 17:10:03 +02007368 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007369#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007370}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007371static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7372{
7373 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7374}
Emeric Brun2b58d042012-09-20 17:10:03 +02007375
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007376/* parse the "curves" bind keyword keyword */
7377static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7378{
7379#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7380 if (!*args[cur_arg + 1]) {
7381 if (err)
7382 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7383 return ERR_ALERT | ERR_FATAL;
7384 }
7385 conf->curves = strdup(args[cur_arg + 1]);
7386 return 0;
7387#else
7388 if (err)
7389 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7390 return ERR_ALERT | ERR_FATAL;
7391#endif
7392}
7393static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7394{
7395 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7396}
7397
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007398/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007399static 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 +02007400{
7401#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7402 if (err)
7403 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7404 return ERR_ALERT | ERR_FATAL;
7405#elif defined(OPENSSL_NO_ECDH)
7406 if (err)
7407 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7408 return ERR_ALERT | ERR_FATAL;
7409#else
7410 if (!*args[cur_arg + 1]) {
7411 if (err)
7412 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7413 return ERR_ALERT | ERR_FATAL;
7414 }
7415
7416 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007417
7418 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007419#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007420}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007421static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7422{
7423 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7424}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007425
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007426/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007427static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7428{
7429 int code;
7430 char *p = args[cur_arg + 1];
7431 unsigned long long *ignerr = &conf->crt_ignerr;
7432
7433 if (!*p) {
7434 if (err)
7435 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7436 return ERR_ALERT | ERR_FATAL;
7437 }
7438
7439 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7440 ignerr = &conf->ca_ignerr;
7441
7442 if (strcmp(p, "all") == 0) {
7443 *ignerr = ~0ULL;
7444 return 0;
7445 }
7446
7447 while (p) {
7448 code = atoi(p);
7449 if ((code <= 0) || (code > 63)) {
7450 if (err)
7451 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7452 args[cur_arg], code, args[cur_arg + 1]);
7453 return ERR_ALERT | ERR_FATAL;
7454 }
7455 *ignerr |= 1ULL << code;
7456 p = strchr(p, ',');
7457 if (p)
7458 p++;
7459 }
7460
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007461 return 0;
7462}
7463
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007464/* parse tls_method_options "no-xxx" and "force-xxx" */
7465static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007466{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007467 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007468 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007469 p = strchr(arg, '-');
7470 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007471 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007472 p++;
7473 if (!strcmp(p, "sslv3"))
7474 v = CONF_SSLV3;
7475 else if (!strcmp(p, "tlsv10"))
7476 v = CONF_TLSV10;
7477 else if (!strcmp(p, "tlsv11"))
7478 v = CONF_TLSV11;
7479 else if (!strcmp(p, "tlsv12"))
7480 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007481 else if (!strcmp(p, "tlsv13"))
7482 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007483 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007484 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007485 if (!strncmp(arg, "no-", 3))
7486 methods->flags |= methodVersions[v].flag;
7487 else if (!strncmp(arg, "force-", 6))
7488 methods->min = methods->max = v;
7489 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007490 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007491 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007492 fail:
7493 if (err)
7494 memprintf(err, "'%s' : option not implemented", arg);
7495 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007496}
7497
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007498static 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 +02007499{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007500 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007501}
7502
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007503static 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 +02007504{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007505 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7506}
7507
7508/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7509static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7510{
7511 uint16_t i, v = 0;
7512 char *argv = args[cur_arg + 1];
7513 if (!*argv) {
7514 if (err)
7515 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7516 return ERR_ALERT | ERR_FATAL;
7517 }
7518 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7519 if (!strcmp(argv, methodVersions[i].name))
7520 v = i;
7521 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007522 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007523 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007524 return ERR_ALERT | ERR_FATAL;
7525 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007526 if (!strcmp("ssl-min-ver", args[cur_arg]))
7527 methods->min = v;
7528 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7529 methods->max = v;
7530 else {
7531 if (err)
7532 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7533 return ERR_ALERT | ERR_FATAL;
7534 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007535 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007536}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007537
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007538static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7539{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007540#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007541 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 +02007542#endif
7543 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7544}
7545
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007546static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7547{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007548 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007549}
7550
7551static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7552{
7553 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7554}
7555
Emeric Brun2d0c4822012-10-02 13:45:20 +02007556/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007557static 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 +02007558{
Emeric Brun89675492012-10-05 13:48:26 +02007559 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007560 return 0;
7561}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007562
Olivier Houchardc2aae742017-09-22 18:26:28 +02007563/* parse the "allow-0rtt" bind keyword */
7564static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7565{
7566 conf->early_data = 1;
7567 return 0;
7568}
7569
7570static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7571{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007572 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007573 return 0;
7574}
7575
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007576/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007577static 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 +02007578{
Bernard Spil13c53f82018-02-15 13:34:58 +01007579#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007580 char *p1, *p2;
7581
7582 if (!*args[cur_arg + 1]) {
7583 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7584 return ERR_ALERT | ERR_FATAL;
7585 }
7586
7587 free(conf->npn_str);
7588
Willy Tarreau3724da12016-02-12 17:11:12 +01007589 /* the NPN string is built as a suite of (<len> <name>)*,
7590 * so we reuse each comma to store the next <len> and need
7591 * one more for the end of the string.
7592 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007593 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007594 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007595 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7596
7597 /* replace commas with the name length */
7598 p1 = conf->npn_str;
7599 p2 = p1 + 1;
7600 while (1) {
7601 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7602 if (!p2)
7603 p2 = p1 + 1 + strlen(p1 + 1);
7604
7605 if (p2 - (p1 + 1) > 255) {
7606 *p2 = '\0';
7607 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7608 return ERR_ALERT | ERR_FATAL;
7609 }
7610
7611 *p1 = p2 - (p1 + 1);
7612 p1 = p2;
7613
7614 if (!*p2)
7615 break;
7616
7617 *(p2++) = '\0';
7618 }
7619 return 0;
7620#else
7621 if (err)
7622 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7623 return ERR_ALERT | ERR_FATAL;
7624#endif
7625}
7626
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007627static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7628{
7629 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7630}
7631
Willy Tarreauab861d32013-04-02 02:30:41 +02007632/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007633static 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 +02007634{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007635#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007636 char *p1, *p2;
7637
7638 if (!*args[cur_arg + 1]) {
7639 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7640 return ERR_ALERT | ERR_FATAL;
7641 }
7642
7643 free(conf->alpn_str);
7644
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007645 /* the ALPN string is built as a suite of (<len> <name>)*,
7646 * so we reuse each comma to store the next <len> and need
7647 * one more for the end of the string.
7648 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007649 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007650 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007651 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7652
7653 /* replace commas with the name length */
7654 p1 = conf->alpn_str;
7655 p2 = p1 + 1;
7656 while (1) {
7657 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7658 if (!p2)
7659 p2 = p1 + 1 + strlen(p1 + 1);
7660
7661 if (p2 - (p1 + 1) > 255) {
7662 *p2 = '\0';
7663 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7664 return ERR_ALERT | ERR_FATAL;
7665 }
7666
7667 *p1 = p2 - (p1 + 1);
7668 p1 = p2;
7669
7670 if (!*p2)
7671 break;
7672
7673 *(p2++) = '\0';
7674 }
7675 return 0;
7676#else
7677 if (err)
7678 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7679 return ERR_ALERT | ERR_FATAL;
7680#endif
7681}
7682
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007683static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7684{
7685 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7686}
7687
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007688/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007689static 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 +02007690{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007691 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007692 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007693
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007694 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7695 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007696#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7697 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7698 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7699#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007700 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007701 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7702 if (!conf->ssl_conf.ssl_methods.min)
7703 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7704 if (!conf->ssl_conf.ssl_methods.max)
7705 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007706
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007707 return 0;
7708}
7709
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007710/* parse the "prefer-client-ciphers" bind keyword */
7711static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7712{
7713 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7714 return 0;
7715}
7716
Christopher Faulet31af49d2015-06-09 17:29:50 +02007717/* parse the "generate-certificates" bind keyword */
7718static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7719{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007720#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007721 conf->generate_certs = 1;
7722#else
7723 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7724 err && *err ? *err : "");
7725#endif
7726 return 0;
7727}
7728
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007729/* parse the "strict-sni" bind keyword */
7730static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7731{
7732 conf->strict_sni = 1;
7733 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007734}
7735
7736/* parse the "tls-ticket-keys" bind keyword */
7737static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7738{
7739#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7740 FILE *f;
7741 int i = 0;
7742 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007743 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007744
7745 if (!*args[cur_arg + 1]) {
7746 if (err)
7747 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7748 return ERR_ALERT | ERR_FATAL;
7749 }
7750
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007751 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007752 if (keys_ref) {
7753 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007754 conf->keys_ref = keys_ref;
7755 return 0;
7756 }
7757
Vincent Bernat02779b62016-04-03 13:48:43 +02007758 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007759 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007760
7761 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7762 if (err)
7763 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7764 return ERR_ALERT | ERR_FATAL;
7765 }
7766
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007767 keys_ref->filename = strdup(args[cur_arg + 1]);
7768
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007769 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7770 int len = strlen(thisline);
7771 /* Strip newline characters from the end */
7772 if(thisline[len - 1] == '\n')
7773 thisline[--len] = 0;
7774
7775 if(thisline[len - 1] == '\r')
7776 thisline[--len] = 0;
7777
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007778 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 +01007779 if (err)
7780 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007781 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007782 return ERR_ALERT | ERR_FATAL;
7783 }
7784 i++;
7785 }
7786
7787 if (i < TLS_TICKETS_NO) {
7788 if (err)
7789 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 +02007790 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007791 return ERR_ALERT | ERR_FATAL;
7792 }
7793
7794 fclose(f);
7795
7796 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007797 i -= 2;
7798 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007799 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007800 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007801 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007802 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007803
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007804 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7805
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007806 return 0;
7807#else
7808 if (err)
7809 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7810 return ERR_ALERT | ERR_FATAL;
7811#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007812}
7813
Emeric Brund94b3fe2012-09-20 18:23:56 +02007814/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007815static 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 +02007816{
7817 if (!*args[cur_arg + 1]) {
7818 if (err)
7819 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7820 return ERR_ALERT | ERR_FATAL;
7821 }
7822
7823 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007824 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007825 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007826 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007827 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007828 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007829 else {
7830 if (err)
7831 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7832 args[cur_arg], args[cur_arg + 1]);
7833 return ERR_ALERT | ERR_FATAL;
7834 }
7835
7836 return 0;
7837}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007838static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7839{
7840 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7841}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007842
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007843/* parse the "no-ca-names" bind keyword */
7844static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7845{
7846 conf->no_ca_names = 1;
7847 return 0;
7848}
7849static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7850{
7851 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7852}
7853
Willy Tarreau92faadf2012-10-10 23:04:25 +02007854/************** "server" keywords ****************/
7855
Emeric Brunef42d922012-10-11 16:11:36 +02007856/* parse the "ca-file" server keyword */
7857static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7858{
7859 if (!*args[*cur_arg + 1]) {
7860 if (err)
7861 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7862 return ERR_ALERT | ERR_FATAL;
7863 }
7864
Willy Tarreauef934602016-12-22 23:12:01 +01007865 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7866 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007867 else
7868 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7869
7870 return 0;
7871}
7872
Olivier Houchard9130a962017-10-17 17:33:43 +02007873/* parse the "check-sni" server keyword */
7874static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7875{
7876 if (!*args[*cur_arg + 1]) {
7877 if (err)
7878 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7879 return ERR_ALERT | ERR_FATAL;
7880 }
7881
7882 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7883 if (!newsrv->check.sni) {
7884 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7885 return ERR_ALERT | ERR_FATAL;
7886 }
7887 return 0;
7888
7889}
7890
Willy Tarreau92faadf2012-10-10 23:04:25 +02007891/* parse the "check-ssl" server keyword */
7892static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7893{
7894 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007895 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7896 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007897#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7898 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
7899 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
7900#endif
Willy Tarreauef934602016-12-22 23:12:01 +01007901 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007902 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7903 if (!newsrv->ssl_ctx.methods.min)
7904 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7905 if (!newsrv->ssl_ctx.methods.max)
7906 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7907
Willy Tarreau92faadf2012-10-10 23:04:25 +02007908 return 0;
7909}
7910
7911/* parse the "ciphers" server keyword */
7912static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7913{
7914 if (!*args[*cur_arg + 1]) {
7915 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7916 return ERR_ALERT | ERR_FATAL;
7917 }
7918
7919 free(newsrv->ssl_ctx.ciphers);
7920 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7921 return 0;
7922}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007923
7924#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7925/* parse the "ciphersuites" server keyword */
7926static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7927{
7928 if (!*args[*cur_arg + 1]) {
7929 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7930 return ERR_ALERT | ERR_FATAL;
7931 }
7932
7933 free(newsrv->ssl_ctx.ciphersuites);
7934 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
7935 return 0;
7936}
7937#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02007938
Emeric Brunef42d922012-10-11 16:11:36 +02007939/* parse the "crl-file" server keyword */
7940static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7941{
7942#ifndef X509_V_FLAG_CRL_CHECK
7943 if (err)
7944 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7945 return ERR_ALERT | ERR_FATAL;
7946#else
7947 if (!*args[*cur_arg + 1]) {
7948 if (err)
7949 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7950 return ERR_ALERT | ERR_FATAL;
7951 }
7952
Willy Tarreauef934602016-12-22 23:12:01 +01007953 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7954 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007955 else
7956 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7957
7958 return 0;
7959#endif
7960}
7961
Emeric Bruna7aa3092012-10-26 12:58:00 +02007962/* parse the "crt" server keyword */
7963static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7964{
7965 if (!*args[*cur_arg + 1]) {
7966 if (err)
7967 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7968 return ERR_ALERT | ERR_FATAL;
7969 }
7970
Willy Tarreauef934602016-12-22 23:12:01 +01007971 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007972 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007973 else
7974 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7975
7976 return 0;
7977}
Emeric Brunef42d922012-10-11 16:11:36 +02007978
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007979/* parse the "no-check-ssl" server keyword */
7980static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7981{
7982 newsrv->check.use_ssl = 0;
7983 free(newsrv->ssl_ctx.ciphers);
7984 newsrv->ssl_ctx.ciphers = NULL;
7985 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7986 return 0;
7987}
7988
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007989/* parse the "no-send-proxy-v2-ssl" server keyword */
7990static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7991{
7992 newsrv->pp_opts &= ~SRV_PP_V2;
7993 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7994 return 0;
7995}
7996
7997/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7998static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7999{
8000 newsrv->pp_opts &= ~SRV_PP_V2;
8001 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8002 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8003 return 0;
8004}
8005
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008006/* parse the "no-ssl" server keyword */
8007static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8008{
8009 newsrv->use_ssl = 0;
8010 free(newsrv->ssl_ctx.ciphers);
8011 newsrv->ssl_ctx.ciphers = NULL;
8012 return 0;
8013}
8014
Olivier Houchard522eea72017-11-03 16:27:47 +01008015/* parse the "allow-0rtt" server keyword */
8016static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8017{
8018 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8019 return 0;
8020}
8021
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008022/* parse the "no-ssl-reuse" server keyword */
8023static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8024{
8025 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8026 return 0;
8027}
8028
Emeric Brunf9c5c472012-10-11 15:28:34 +02008029/* parse the "no-tls-tickets" server keyword */
8030static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8031{
8032 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8033 return 0;
8034}
David Safb76832014-05-08 23:42:08 -04008035/* parse the "send-proxy-v2-ssl" server keyword */
8036static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8037{
8038 newsrv->pp_opts |= SRV_PP_V2;
8039 newsrv->pp_opts |= SRV_PP_V2_SSL;
8040 return 0;
8041}
8042
8043/* parse the "send-proxy-v2-ssl-cn" server keyword */
8044static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8045{
8046 newsrv->pp_opts |= SRV_PP_V2;
8047 newsrv->pp_opts |= SRV_PP_V2_SSL;
8048 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8049 return 0;
8050}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008051
Willy Tarreau732eac42015-07-09 11:40:25 +02008052/* parse the "sni" server keyword */
8053static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8054{
8055#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8056 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8057 return ERR_ALERT | ERR_FATAL;
8058#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008059 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008060
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008061 arg = args[*cur_arg + 1];
8062 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008063 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8064 return ERR_ALERT | ERR_FATAL;
8065 }
8066
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008067 free(newsrv->sni_expr);
8068 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008069
Willy Tarreau732eac42015-07-09 11:40:25 +02008070 return 0;
8071#endif
8072}
8073
Willy Tarreau92faadf2012-10-10 23:04:25 +02008074/* parse the "ssl" server keyword */
8075static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8076{
8077 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008078 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8079 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008080#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8081 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8082 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8083#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008084 return 0;
8085}
8086
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008087/* parse the "ssl-reuse" server keyword */
8088static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8089{
8090 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8091 return 0;
8092}
8093
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008094/* parse the "tls-tickets" server keyword */
8095static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8096{
8097 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8098 return 0;
8099}
8100
Emeric Brunef42d922012-10-11 16:11:36 +02008101/* parse the "verify" server keyword */
8102static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8103{
8104 if (!*args[*cur_arg + 1]) {
8105 if (err)
8106 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8107 return ERR_ALERT | ERR_FATAL;
8108 }
8109
8110 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008111 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008112 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008113 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008114 else {
8115 if (err)
8116 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8117 args[*cur_arg], args[*cur_arg + 1]);
8118 return ERR_ALERT | ERR_FATAL;
8119 }
8120
Evan Broderbe554312013-06-27 00:05:25 -07008121 return 0;
8122}
8123
8124/* parse the "verifyhost" server keyword */
8125static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8126{
8127 if (!*args[*cur_arg + 1]) {
8128 if (err)
8129 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8130 return ERR_ALERT | ERR_FATAL;
8131 }
8132
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008133 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008134 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8135
Emeric Brunef42d922012-10-11 16:11:36 +02008136 return 0;
8137}
8138
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008139/* parse the "ssl-default-bind-options" keyword in global section */
8140static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8141 struct proxy *defpx, const char *file, int line,
8142 char **err) {
8143 int i = 1;
8144
8145 if (*(args[i]) == 0) {
8146 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8147 return -1;
8148 }
8149 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008150 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008151 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008152 else if (!strcmp(args[i], "prefer-client-ciphers"))
8153 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008154 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8155 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8156 i++;
8157 else {
8158 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8159 return -1;
8160 }
8161 }
8162 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008163 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8164 return -1;
8165 }
8166 i++;
8167 }
8168 return 0;
8169}
8170
8171/* parse the "ssl-default-server-options" keyword in global section */
8172static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8173 struct proxy *defpx, const char *file, int line,
8174 char **err) {
8175 int i = 1;
8176
8177 if (*(args[i]) == 0) {
8178 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8179 return -1;
8180 }
8181 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008182 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008183 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008184 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8185 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8186 i++;
8187 else {
8188 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8189 return -1;
8190 }
8191 }
8192 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008193 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8194 return -1;
8195 }
8196 i++;
8197 }
8198 return 0;
8199}
8200
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008201/* parse the "ca-base" / "crt-base" keywords in global section.
8202 * Returns <0 on alert, >0 on warning, 0 on success.
8203 */
8204static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8205 struct proxy *defpx, const char *file, int line,
8206 char **err)
8207{
8208 char **target;
8209
Willy Tarreauef934602016-12-22 23:12:01 +01008210 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008211
8212 if (too_many_args(1, args, err, NULL))
8213 return -1;
8214
8215 if (*target) {
8216 memprintf(err, "'%s' already specified.", args[0]);
8217 return -1;
8218 }
8219
8220 if (*(args[1]) == 0) {
8221 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8222 return -1;
8223 }
8224 *target = strdup(args[1]);
8225 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008226}
8227
8228/* parse the "ssl-mode-async" keyword in global section.
8229 * Returns <0 on alert, >0 on warning, 0 on success.
8230 */
8231static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8232 struct proxy *defpx, const char *file, int line,
8233 char **err)
8234{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008235#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008236 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008237 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008238 return 0;
8239#else
8240 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8241 return -1;
8242#endif
8243}
8244
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008245#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008246static int ssl_check_async_engine_count(void) {
8247 int err_code = 0;
8248
Emeric Brun3854e012017-05-17 20:42:48 +02008249 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008250 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008251 err_code = ERR_ABORT;
8252 }
8253 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008254}
8255
Grant Zhang872f9c22017-01-21 01:10:18 +00008256/* parse the "ssl-engine" keyword in global section.
8257 * Returns <0 on alert, >0 on warning, 0 on success.
8258 */
8259static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8260 struct proxy *defpx, const char *file, int line,
8261 char **err)
8262{
8263 char *algo;
8264 int ret = -1;
8265
8266 if (*(args[1]) == 0) {
8267 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8268 return ret;
8269 }
8270
8271 if (*(args[2]) == 0) {
8272 /* if no list of algorithms is given, it defaults to ALL */
8273 algo = strdup("ALL");
8274 goto add_engine;
8275 }
8276
8277 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8278 if (strcmp(args[2], "algo") != 0) {
8279 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8280 return ret;
8281 }
8282
8283 if (*(args[3]) == 0) {
8284 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8285 return ret;
8286 }
8287 algo = strdup(args[3]);
8288
8289add_engine:
8290 if (ssl_init_single_engine(args[1], algo)==0) {
8291 openssl_engines_initialized++;
8292 ret = 0;
8293 }
8294 free(algo);
8295 return ret;
8296}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008297#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008298
Willy Tarreauf22e9682016-12-21 23:23:19 +01008299/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8300 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8301 */
8302static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8303 struct proxy *defpx, const char *file, int line,
8304 char **err)
8305{
8306 char **target;
8307
Willy Tarreauef934602016-12-22 23:12:01 +01008308 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008309
8310 if (too_many_args(1, args, err, NULL))
8311 return -1;
8312
8313 if (*(args[1]) == 0) {
8314 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8315 return -1;
8316 }
8317
8318 free(*target);
8319 *target = strdup(args[1]);
8320 return 0;
8321}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008322
8323#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8324/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8325 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8326 */
8327static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8328 struct proxy *defpx, const char *file, int line,
8329 char **err)
8330{
8331 char **target;
8332
8333 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8334
8335 if (too_many_args(1, args, err, NULL))
8336 return -1;
8337
8338 if (*(args[1]) == 0) {
8339 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8340 return -1;
8341 }
8342
8343 free(*target);
8344 *target = strdup(args[1]);
8345 return 0;
8346}
8347#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008348
Willy Tarreau9ceda382016-12-21 23:13:03 +01008349/* parse various global tune.ssl settings consisting in positive integers.
8350 * Returns <0 on alert, >0 on warning, 0 on success.
8351 */
8352static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8353 struct proxy *defpx, const char *file, int line,
8354 char **err)
8355{
8356 int *target;
8357
8358 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8359 target = &global.tune.sslcachesize;
8360 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008361 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008362 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008363 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008364 else if (strcmp(args[0], "maxsslconn") == 0)
8365 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008366 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8367 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008368 else {
8369 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8370 return -1;
8371 }
8372
8373 if (too_many_args(1, args, err, NULL))
8374 return -1;
8375
8376 if (*(args[1]) == 0) {
8377 memprintf(err, "'%s' expects an integer argument.", args[0]);
8378 return -1;
8379 }
8380
8381 *target = atoi(args[1]);
8382 if (*target < 0) {
8383 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8384 return -1;
8385 }
8386 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008387}
8388
8389static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8390 struct proxy *defpx, const char *file, int line,
8391 char **err)
8392{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008393 int ret;
8394
8395 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8396 if (ret != 0)
8397 return ret;
8398
Willy Tarreaubafbe012017-11-24 17:34:44 +01008399 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008400 memprintf(err, "'%s' is already configured.", args[0]);
8401 return -1;
8402 }
8403
Willy Tarreaubafbe012017-11-24 17:34:44 +01008404 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8405 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008406 memprintf(err, "Out of memory error.");
8407 return -1;
8408 }
8409 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008410}
8411
8412/* parse "ssl.force-private-cache".
8413 * Returns <0 on alert, >0 on warning, 0 on success.
8414 */
8415static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8416 struct proxy *defpx, const char *file, int line,
8417 char **err)
8418{
8419 if (too_many_args(0, args, err, NULL))
8420 return -1;
8421
Willy Tarreauef934602016-12-22 23:12:01 +01008422 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008423 return 0;
8424}
8425
8426/* parse "ssl.lifetime".
8427 * Returns <0 on alert, >0 on warning, 0 on success.
8428 */
8429static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8430 struct proxy *defpx, const char *file, int line,
8431 char **err)
8432{
8433 const char *res;
8434
8435 if (too_many_args(1, args, err, NULL))
8436 return -1;
8437
8438 if (*(args[1]) == 0) {
8439 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8440 return -1;
8441 }
8442
Willy Tarreauef934602016-12-22 23:12:01 +01008443 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008444 if (res) {
8445 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8446 return -1;
8447 }
8448 return 0;
8449}
8450
8451#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008452/* parse "ssl-dh-param-file".
8453 * Returns <0 on alert, >0 on warning, 0 on success.
8454 */
8455static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8456 struct proxy *defpx, const char *file, int line,
8457 char **err)
8458{
8459 if (too_many_args(1, args, err, NULL))
8460 return -1;
8461
8462 if (*(args[1]) == 0) {
8463 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8464 return -1;
8465 }
8466
8467 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8468 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8469 return -1;
8470 }
8471 return 0;
8472}
8473
Willy Tarreau9ceda382016-12-21 23:13:03 +01008474/* parse "ssl.default-dh-param".
8475 * Returns <0 on alert, >0 on warning, 0 on success.
8476 */
8477static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8478 struct proxy *defpx, const char *file, int line,
8479 char **err)
8480{
8481 if (too_many_args(1, args, err, NULL))
8482 return -1;
8483
8484 if (*(args[1]) == 0) {
8485 memprintf(err, "'%s' expects an integer argument.", args[0]);
8486 return -1;
8487 }
8488
Willy Tarreauef934602016-12-22 23:12:01 +01008489 global_ssl.default_dh_param = atoi(args[1]);
8490 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008491 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8492 return -1;
8493 }
8494 return 0;
8495}
8496#endif
8497
8498
William Lallemand32af2032016-10-29 18:09:35 +02008499/* This function is used with TLS ticket keys management. It permits to browse
8500 * each reference. The variable <getnext> must contain the current node,
8501 * <end> point to the root node.
8502 */
8503#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8504static inline
8505struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8506{
8507 struct tls_keys_ref *ref = getnext;
8508
8509 while (1) {
8510
8511 /* Get next list entry. */
8512 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8513
8514 /* If the entry is the last of the list, return NULL. */
8515 if (&ref->list == end)
8516 return NULL;
8517
8518 return ref;
8519 }
8520}
8521
8522static inline
8523struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8524{
8525 int id;
8526 char *error;
8527
8528 /* If the reference starts by a '#', this is numeric id. */
8529 if (reference[0] == '#') {
8530 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8531 id = strtol(reference + 1, &error, 10);
8532 if (*error != '\0')
8533 return NULL;
8534
8535 /* Perform the unique id lookup. */
8536 return tlskeys_ref_lookupid(id);
8537 }
8538
8539 /* Perform the string lookup. */
8540 return tlskeys_ref_lookup(reference);
8541}
8542#endif
8543
8544
8545#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8546
8547static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8548
8549static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8550 return cli_io_handler_tlskeys_files(appctx);
8551}
8552
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008553/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8554 * (next index to be dumped), and cli.p0 (next key reference).
8555 */
William Lallemand32af2032016-10-29 18:09:35 +02008556static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8557
8558 struct stream_interface *si = appctx->owner;
8559
8560 switch (appctx->st2) {
8561 case STAT_ST_INIT:
8562 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008563 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008564 * later and restart at the state "STAT_ST_INIT".
8565 */
8566 chunk_reset(&trash);
8567
8568 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8569 chunk_appendf(&trash, "# id secret\n");
8570 else
8571 chunk_appendf(&trash, "# id (file)\n");
8572
Willy Tarreau06d80a92017-10-19 14:32:15 +02008573 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008574 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008575 return 0;
8576 }
8577
William Lallemand32af2032016-10-29 18:09:35 +02008578 /* Now, we start the browsing of the references lists.
8579 * Note that the following call to LIST_ELEM return bad pointer. The only
8580 * available field of this pointer is <list>. It is used with the function
8581 * tlskeys_list_get_next() for retruning the first available entry
8582 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008583 if (appctx->ctx.cli.p0 == NULL) {
8584 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8585 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008586 }
8587
8588 appctx->st2 = STAT_ST_LIST;
8589 /* fall through */
8590
8591 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008592 while (appctx->ctx.cli.p0) {
8593 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008594
8595 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008596 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008597 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008598
8599 if (appctx->ctx.cli.i1 == 0)
8600 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8601
William Lallemand32af2032016-10-29 18:09:35 +02008602 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008603 int head;
8604
8605 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8606 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008607 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008608 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008609
8610 chunk_reset(t2);
8611 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008612 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8613 sizeof(struct tls_sess_key),
8614 t2->area, t2->size);
8615 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8616 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008617
Willy Tarreau06d80a92017-10-19 14:32:15 +02008618 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008619 /* let's try again later from this stream. We add ourselves into
8620 * this stream's users so that it can remove us upon termination.
8621 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008622 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008623 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008624 return 0;
8625 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008626 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008627 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008628 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008629 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008630 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008631 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008632 /* let's try again later from this stream. We add ourselves into
8633 * this stream's users so that it can remove us upon termination.
8634 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008635 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008636 return 0;
8637 }
8638
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008639 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008640 break;
8641
8642 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008643 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008644 }
8645
8646 appctx->st2 = STAT_ST_FIN;
8647 /* fall through */
8648
8649 default:
8650 appctx->st2 = STAT_ST_FIN;
8651 return 1;
8652 }
8653 return 0;
8654}
8655
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008656/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008657static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008658{
William Lallemand32af2032016-10-29 18:09:35 +02008659 /* no parameter, shows only file list */
8660 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008661 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008662 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008663 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008664 }
8665
8666 if (args[2][0] == '*') {
8667 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008668 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008669 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008670 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8671 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008672 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008673 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008674 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008675 return 1;
8676 }
8677 }
William Lallemand32af2032016-10-29 18:09:35 +02008678 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008679 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008680}
8681
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008682static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008683{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008684 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008685 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008686
William Lallemand32af2032016-10-29 18:09:35 +02008687 /* Expect two parameters: the filename and the new new TLS key in encoding */
8688 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008689 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008690 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 +01008691 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008692 return 1;
8693 }
8694
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008695 ref = tlskeys_ref_lookup_ref(args[3]);
8696 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008697 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008698 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008699 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008700 return 1;
8701 }
8702
Willy Tarreau1c913e42018-08-22 05:26:57 +02008703 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8704 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008705 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008706 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008707 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008708 return 1;
8709 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008710 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008711 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008712 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008713 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008714 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008715 return 1;
8716
8717}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008718#endif
William Lallemand32af2032016-10-29 18:09:35 +02008719
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008720static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008721{
8722#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8723 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008724 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008725
8726 if (!payload)
8727 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008728
8729 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008730 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008731 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008732 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008733 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008734 return 1;
8735 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008736
8737 /* remove \r and \n from the payload */
8738 for (i = 0, j = 0; payload[i]; i++) {
8739 if (payload[i] == '\r' || payload[i] == '\n')
8740 continue;
8741 payload[j++] = payload[i];
8742 }
8743 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008744
Willy Tarreau1c913e42018-08-22 05:26:57 +02008745 ret = base64dec(payload, j, trash.area, trash.size);
8746 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008747 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008748 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008749 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008750 return 1;
8751 }
8752
Willy Tarreau1c913e42018-08-22 05:26:57 +02008753 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008754 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8755 if (err) {
8756 memprintf(&err, "%s.\n", err);
8757 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008758 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008759 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008760 else {
8761 appctx->ctx.cli.severity = LOG_ERR;
8762 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8763 appctx->st0 = CLI_ST_PRINT;
8764 }
William Lallemand32af2032016-10-29 18:09:35 +02008765 return 1;
8766 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008767 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008768 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008769 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008770 return 1;
8771#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008772 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008773 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 +01008774 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008775 return 1;
8776#endif
8777
8778}
8779
8780/* register cli keywords */
8781static struct cli_kw_list cli_kws = {{ },{
8782#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8783 { { "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 +02008784 { { "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 +02008785#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008786 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008787 { { NULL }, NULL, NULL, NULL }
8788}};
8789
8790
Willy Tarreau7875d092012-09-10 08:20:03 +02008791/* Note: must not be declared <const> as its list will be overwritten.
8792 * Please take care of keeping this list alphabetically sorted.
8793 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008794static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008795 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008796 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008797 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008798 { "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 +02008799 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008800 { "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 +02008801 { "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 -04008802#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008803 { "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 -04008804#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008805#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8806 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8807#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008808 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8809 { "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 +01008810 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008811 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008812 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8813 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8814 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8815 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8816 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8817 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8818 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8819 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008820 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008821 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8822 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008823 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008824 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8825 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8826 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8827 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8828 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8829 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8830 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008831 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008832 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008833 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008834 { "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 +01008835 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008836 { "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 +02008837 { "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 +01008838 { "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 +02008839 { "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 +01008840#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008841 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008842#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008843#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008844 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008845#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008846 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008847#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02008848 { "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 -04008849#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008850 { "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 -04008851#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008852 { "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 -04008853#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008854#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8855 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8856#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04008857#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008858 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008859#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008860 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8861 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8862 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8863 { "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 +02008864 { NULL, NULL, 0, 0, 0 },
8865}};
8866
8867/* Note: must not be declared <const> as its list will be overwritten.
8868 * Please take care of keeping this list alphabetically sorted.
8869 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008870static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008871 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8872 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008873 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008874}};
8875
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008876/* Note: must not be declared <const> as its list will be overwritten.
8877 * Please take care of keeping this list alphabetically sorted, doing so helps
8878 * all code contributors.
8879 * Optional keywords are also declared with a NULL ->parse() function so that
8880 * the config parser can report an appropriate error when a known keyword was
8881 * not enabled.
8882 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008883static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008884 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008885 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8886 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8887 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008888#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8889 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
8890#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008891 { "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 +01008892 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008893 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008894 { "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 +01008895 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008896 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8897 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008898 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8899 { NULL, NULL, 0 },
8900};
8901
Willy Tarreau51fb7652012-09-18 18:24:39 +02008902static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008903 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008904 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8905 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8906 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8907 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8908 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8909 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008910#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8911 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
8912#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008913 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8914 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8915 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8916 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8917 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8918 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8919 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8920 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8921 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8922 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008923 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008924 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008925 { "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 +02008926 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8927 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8928 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8929 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008930 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008931 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8932 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008933 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8934 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008935 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8936 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8937 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8938 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8939 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008940 { NULL, NULL, 0 },
8941}};
Emeric Brun46591952012-05-18 15:47:34 +02008942
Willy Tarreau92faadf2012-10-10 23:04:25 +02008943/* Note: must not be declared <const> as its list will be overwritten.
8944 * Please take care of keeping this list alphabetically sorted, doing so helps
8945 * all code contributors.
8946 * Optional keywords are also declared with a NULL ->parse() function so that
8947 * the config parser can report an appropriate error when a known keyword was
8948 * not enabled.
8949 */
8950static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008951 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008952 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008953 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008954 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8955 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008956#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8957 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
8958#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008959 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8960 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8961 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8962 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8963 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8964 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8965 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8966 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8967 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8968 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8969 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8970 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8971 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8972 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8973 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8974 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8975 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8976 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8977 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8978 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8979 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8980 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8981 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8982 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8983 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8984 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8985 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8986 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008987 { NULL, NULL, 0, 0 },
8988}};
8989
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008990static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008991 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8992 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008993 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008994 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8995 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008996#ifndef OPENSSL_NO_DH
8997 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8998#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008999 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009000#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009001 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009002#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009003 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9004#ifndef OPENSSL_NO_DH
9005 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9006#endif
9007 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9008 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9009 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9010 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009011 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009012 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9013 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009014#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9015 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9016 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9017#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009018 { 0, NULL, NULL },
9019}};
9020
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009021/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009022static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009023 .snd_buf = ssl_sock_from_buf,
9024 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009025 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009026 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009027 .rcv_pipe = NULL,
9028 .snd_pipe = NULL,
9029 .shutr = NULL,
9030 .shutw = ssl_sock_shutw,
9031 .close = ssl_sock_close,
9032 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009033 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009034 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009035 .prepare_srv = ssl_sock_prepare_srv_ctx,
9036 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009037 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009038 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009039};
9040
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009041enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9042 struct session *sess, struct stream *s, int flags)
9043{
9044 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009045 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009046
9047 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009048 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009049
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009050 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009051 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009052 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009053 s->req.flags |= CF_READ_NULL;
9054 return ACT_RET_YIELD;
9055 }
9056 }
9057 return (ACT_RET_CONT);
9058}
9059
9060static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9061{
9062 rule->action_ptr = ssl_action_wait_for_hs;
9063
9064 return ACT_RET_PRS_OK;
9065}
9066
9067static struct action_kw_list http_req_actions = {ILH, {
9068 { "wait-for-handshake", ssl_parse_wait_for_hs },
9069 { /* END */ }
9070}};
9071
Daniel Jakots54ffb912015-11-06 20:02:41 +01009072#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009073
9074static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9075{
9076 if (ptr) {
9077 chunk_destroy(ptr);
9078 free(ptr);
9079 }
9080}
9081
9082#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009083static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9084{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009085 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009086}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009087
Emeric Brun46591952012-05-18 15:47:34 +02009088__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009089static void __ssl_sock_init(void)
9090{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009091 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009092 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009093
Emeric Brun46591952012-05-18 15:47:34 +02009094 STACK_OF(SSL_COMP)* cm;
9095
Willy Tarreauef934602016-12-22 23:12:01 +01009096 if (global_ssl.listen_default_ciphers)
9097 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9098 if (global_ssl.connect_default_ciphers)
9099 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009100#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9101 if (global_ssl.listen_default_ciphersuites)
9102 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9103 if (global_ssl.connect_default_ciphersuites)
9104 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9105#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009106
Willy Tarreau13e14102016-12-22 20:25:26 +01009107 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009108 SSL_library_init();
9109 cm = SSL_COMP_get_compression_methods();
9110 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009111#ifdef USE_THREAD
9112 ssl_locking_init();
9113#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009114#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009115 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9116#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009117 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009118 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 +01009119 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Willy Tarreau7875d092012-09-10 08:20:03 +02009120 sample_register_fetches(&sample_fetch_keywords);
9121 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009122 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02009123 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009124 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009125 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009126#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009127 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009128 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009129#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009130#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9131 hap_register_post_check(tlskeys_finalize_config);
9132#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009133
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009134 ptr = NULL;
9135 memprintf(&ptr, "Built with OpenSSL version : "
9136#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009137 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009138#else /* OPENSSL_IS_BORINGSSL */
9139 OPENSSL_VERSION_TEXT
9140 "\nRunning on OpenSSL version : %s%s",
9141 SSLeay_version(SSLEAY_VERSION),
9142 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9143#endif
9144 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9145#if OPENSSL_VERSION_NUMBER < 0x00907000L
9146 "no (library version too old)"
9147#elif defined(OPENSSL_NO_TLSEXT)
9148 "no (disabled via OPENSSL_NO_TLSEXT)"
9149#else
9150 "yes"
9151#endif
9152 "", ptr);
9153
9154 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9155#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9156 "yes"
9157#else
9158#ifdef OPENSSL_NO_TLSEXT
9159 "no (because of OPENSSL_NO_TLSEXT)"
9160#else
9161 "no (version might be too old, 0.9.8f min needed)"
9162#endif
9163#endif
9164 "", ptr);
9165
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009166 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9167 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9168 if (methodVersions[i].option)
9169 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009170
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009171 hap_register_build_opts(ptr, 1);
9172
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009173 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9174 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02009175
9176#ifndef OPENSSL_NO_DH
9177 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00009178 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009179#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009180#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009181 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009182#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02009183 /* Load SSL string for the verbose & debug mode. */
9184 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009185
9186 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02009187}
9188
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009189#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009190void ssl_free_engines(void) {
9191 struct ssl_engine_list *wl, *wlb;
9192 /* free up engine list */
9193 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9194 ENGINE_finish(wl->e);
9195 ENGINE_free(wl->e);
9196 LIST_DEL(&wl->list);
9197 free(wl);
9198 }
9199}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009200#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009201
Remi Gacogned3a23c32015-05-28 16:39:47 +02009202#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009203void ssl_free_dh(void) {
9204 if (local_dh_1024) {
9205 DH_free(local_dh_1024);
9206 local_dh_1024 = NULL;
9207 }
9208 if (local_dh_2048) {
9209 DH_free(local_dh_2048);
9210 local_dh_2048 = NULL;
9211 }
9212 if (local_dh_4096) {
9213 DH_free(local_dh_4096);
9214 local_dh_4096 = NULL;
9215 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009216 if (global_dh) {
9217 DH_free(global_dh);
9218 global_dh = NULL;
9219 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009220}
9221#endif
9222
9223__attribute__((destructor))
9224static void __ssl_sock_deinit(void)
9225{
9226#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009227 if (ssl_ctx_lru_tree) {
9228 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009229 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009230 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009231#endif
9232
9233 ERR_remove_state(0);
9234 ERR_free_strings();
9235
9236 EVP_cleanup();
9237
9238#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9239 CRYPTO_cleanup_all_ex_data();
9240#endif
9241}
9242
9243
Emeric Brun46591952012-05-18 15:47:34 +02009244/*
9245 * Local variables:
9246 * c-indent-level: 8
9247 * c-basic-offset: 8
9248 * End:
9249 */