blob: d722867da3e08a583cab8ea1319bb321b16b2bff [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>
Willy Tarreau0108d902018-11-25 19:14:37 +010072#include <common/initcall.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <common/standard.h>
74#include <common/ticks.h>
75#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010076#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010077#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020078
Emeric Brunfc0421f2012-09-07 17:30:07 +020079#include <ebsttree.h>
80
William Lallemand32af2032016-10-29 18:09:35 +020081#include <types/applet.h>
82#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#include <types/global.h>
84#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020085#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020086
Willy Tarreau7875d092012-09-10 08:20:03 +020087#include <proto/acl.h>
88#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020089#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020090#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020091#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020092#include <proto/fd.h>
93#include <proto/freq_ctr.h>
94#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020095#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020096#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020097#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010098#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020099#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +0200100#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +0200101#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200102#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200103#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200104#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200105#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200107#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200108#include <proto/task.h>
109
Willy Tarreau518cedd2014-02-17 15:43:01 +0100110/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200111#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100112#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100113#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200114#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
115
Emeric Brunf282a812012-09-21 15:27:54 +0200116/* bits 0xFFFF0000 are reserved to store verify errors */
117
118/* Verify errors macros */
119#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
120#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
121#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
122
123#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
124#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
125#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200126
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100127/* Supported hash function for TLS tickets */
128#ifdef OPENSSL_NO_SHA256
129#define HASH_FUNCT EVP_sha1
130#else
131#define HASH_FUNCT EVP_sha256
132#endif /* OPENSSL_NO_SHA256 */
133
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200134/* ssl_methods flags for ssl options */
135#define MC_SSL_O_ALL 0x0000
136#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
137#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
138#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
139#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200140#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200141
142/* ssl_methods versions */
143enum {
144 CONF_TLSV_NONE = 0,
145 CONF_TLSV_MIN = 1,
146 CONF_SSLV3 = 1,
147 CONF_TLSV10 = 2,
148 CONF_TLSV11 = 3,
149 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200150 CONF_TLSV13 = 5,
151 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200152};
153
Emeric Brun850efd52014-01-29 12:24:34 +0100154/* server and bind verify method, it uses a global value as default */
155enum {
156 SSL_SOCK_VERIFY_DEFAULT = 0,
157 SSL_SOCK_VERIFY_REQUIRED = 1,
158 SSL_SOCK_VERIFY_OPTIONAL = 2,
159 SSL_SOCK_VERIFY_NONE = 3,
160};
161
William Lallemand3f85c9a2017-10-09 16:30:50 +0200162
Willy Tarreau71b734c2014-01-28 15:19:44 +0100163int sslconns = 0;
164int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100165static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100166int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200167
Willy Tarreauef934602016-12-22 23:12:01 +0100168static struct {
169 char *crt_base; /* base directory path for certificates */
170 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000171 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100172
173 char *listen_default_ciphers;
174 char *connect_default_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
176 char *listen_default_ciphersuites;
177 char *connect_default_ciphersuites;
178#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100179 int listen_default_ssloptions;
180 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200181 struct tls_version_filter listen_default_sslmethods;
182 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100183
184 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
185 unsigned int life_time; /* SSL session lifetime in seconds */
186 unsigned int max_record; /* SSL max record size */
187 unsigned int default_dh_param; /* SSL maximum DH parameter size */
188 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100189 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200197#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100221};
222
Emeric Brun821bb9b2017-06-15 16:37:39 +0200223#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100224
Emeric Brun821bb9b2017-06-15 16:37:39 +0200225static HA_RWLOCK_T *ssl_rwlocks;
226
227
228unsigned long ssl_id_function(void)
229{
230 return (unsigned long)tid;
231}
232
233void ssl_locking_function(int mode, int n, const char * file, int line)
234{
235 if (mode & CRYPTO_LOCK) {
236 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100237 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200238 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100239 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200240 }
241 else {
242 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100243 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200244 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100245 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200246 }
247}
248
249static int ssl_locking_init(void)
250{
251 int i;
252
253 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
254 if (!ssl_rwlocks)
255 return -1;
256
257 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100258 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200259
260 CRYPTO_set_id_callback(ssl_id_function);
261 CRYPTO_set_locking_callback(ssl_locking_function);
262
263 return 0;
264}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100265
Emeric Brun821bb9b2017-06-15 16:37:39 +0200266#endif
267
268
269
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100270/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100271struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100272 unsigned long long int xxh64;
273 unsigned char ciphersuite_len;
274 char ciphersuite[0];
275};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100276struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100277static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200278static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100279
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100280static int ssl_pkey_info_index = -1;
281
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200282#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
283struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
284#endif
285
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200286#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000287static unsigned int openssl_engines_initialized;
288struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
289struct ssl_engine_list {
290 struct list list;
291 ENGINE *e;
292};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200293#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000294
Remi Gacogne8de54152014-07-15 11:36:40 +0200295#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200296static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200297static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200298static DH *local_dh_1024 = NULL;
299static DH *local_dh_2048 = NULL;
300static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100301static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200302#endif /* OPENSSL_NO_DH */
303
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100304#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200305/* X509V3 Extensions that will be added on generated certificates */
306#define X509V3_EXT_SIZE 5
307static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
308 "basicConstraints",
309 "nsComment",
310 "subjectKeyIdentifier",
311 "authorityKeyIdentifier",
312 "keyUsage",
313};
314static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
315 "CA:FALSE",
316 "\"OpenSSL Generated Certificate\"",
317 "hash",
318 "keyid,issuer:always",
319 "nonRepudiation,digitalSignature,keyEncipherment"
320};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200321/* LRU cache to store generated certificate */
322static struct lru64_head *ssl_ctx_lru_tree = NULL;
323static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200324static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100325__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200327#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
328
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100329static struct ssl_bind_kw ssl_bind_kws[];
330
yanbzhube2774d2015-12-10 15:07:30 -0500331#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
332/* The order here matters for picking a default context,
333 * keep the most common keytype at the bottom of the list
334 */
335const char *SSL_SOCK_KEYTYPE_NAMES[] = {
336 "dsa",
337 "ecdsa",
338 "rsa"
339};
340#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100341#else
342#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500343#endif
344
William Lallemandc3cd35f2017-11-28 11:04:43 +0100345static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100346static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
347
348#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
349
350#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
351 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
352
353#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
354 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200355
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100356/*
357 * This function gives the detail of the SSL error. It is used only
358 * if the debug mode and the verbose mode are activated. It dump all
359 * the SSL error until the stack was empty.
360 */
361static forceinline void ssl_sock_dump_errors(struct connection *conn)
362{
363 unsigned long ret;
364
365 if (unlikely(global.mode & MODE_DEBUG)) {
366 while(1) {
367 ret = ERR_get_error();
368 if (ret == 0)
369 return;
370 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200371 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100372 ERR_func_error_string(ret), ERR_reason_error_string(ret));
373 }
374 }
375}
376
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200377#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500378/*
379 * struct alignment works here such that the key.key is the same as key_data
380 * Do not change the placement of key_data
381 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200382struct certificate_ocsp {
383 struct ebmb_node key;
384 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200385 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200386 long expire;
387};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200388
yanbzhube2774d2015-12-10 15:07:30 -0500389struct ocsp_cbk_arg {
390 int is_single;
391 int single_kt;
392 union {
393 struct certificate_ocsp *s_ocsp;
394 /*
395 * m_ocsp will have multiple entries dependent on key type
396 * Entry 0 - DSA
397 * Entry 1 - ECDSA
398 * Entry 2 - RSA
399 */
400 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
401 };
402};
403
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200404#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000405static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
406{
407 int err_code = ERR_ABORT;
408 ENGINE *engine;
409 struct ssl_engine_list *el;
410
411 /* grab the structural reference to the engine */
412 engine = ENGINE_by_id(engine_id);
413 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100414 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000415 goto fail_get;
416 }
417
418 if (!ENGINE_init(engine)) {
419 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100420 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000421 goto fail_init;
422 }
423
424 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100425 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000426 goto fail_set_method;
427 }
428
429 el = calloc(1, sizeof(*el));
430 el->e = engine;
431 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100432 nb_engines++;
433 if (global_ssl.async)
434 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000435 return 0;
436
437fail_set_method:
438 /* release the functional reference from ENGINE_init() */
439 ENGINE_finish(engine);
440
441fail_init:
442 /* release the structural reference from ENGINE_by_id() */
443 ENGINE_free(engine);
444
445fail_get:
446 return err_code;
447}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200448#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000449
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200450#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200451/*
452 * openssl async fd handler
453 */
454static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000455{
456 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000457
Emeric Brun3854e012017-05-17 20:42:48 +0200458 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000459 * to poll this fd until it is requested
460 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000461 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000462 fd_cant_recv(fd);
463
464 /* crypto engine is available, let's notify the associated
465 * connection that it can pursue its processing.
466 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000467 __conn_sock_want_recv(conn);
468 __conn_sock_want_send(conn);
469 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000470}
471
Emeric Brun3854e012017-05-17 20:42:48 +0200472/*
473 * openssl async delayed SSL_free handler
474 */
475static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000476{
477 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200478 OSSL_ASYNC_FD all_fd[32];
479 size_t num_all_fds = 0;
480 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481
Emeric Brun3854e012017-05-17 20:42:48 +0200482 /* We suppose that the async job for a same SSL *
483 * are serialized. So if we are awake it is
484 * because the running job has just finished
485 * and we can remove all async fds safely
486 */
487 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
488 if (num_all_fds > 32) {
489 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
490 return;
491 }
492
493 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
494 for (i=0 ; i < num_all_fds ; i++)
495 fd_remove(all_fd[i]);
496
497 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000498 SSL_free(ssl);
Emeric Brun7ad43e72018-10-10 14:51:02 +0200499 HA_ATOMIC_SUB(&sslconns, 1);
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200500 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000502/*
Emeric Brun3854e012017-05-17 20:42:48 +0200503 * function used to manage a returned SSL_ERROR_WANT_ASYNC
504 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000505 */
Emeric Brun3854e012017-05-17 20:42:48 +0200506static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000507{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100508 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200509 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000510 size_t num_add_fds = 0;
511 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200512 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513
514 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
515 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200516 if (num_add_fds > 32 || num_del_fds > 32) {
517 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 +0000518 return;
519 }
520
Emeric Brun3854e012017-05-17 20:42:48 +0200521 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000522
Emeric Brun3854e012017-05-17 20:42:48 +0200523 /* We remove unused fds from the fdtab */
524 for (i=0 ; i < num_del_fds ; i++)
525 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000526
Emeric Brun3854e012017-05-17 20:42:48 +0200527 /* We add new fds to the fdtab */
528 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100529 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530 }
531
Emeric Brun3854e012017-05-17 20:42:48 +0200532 num_add_fds = 0;
533 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
534 if (num_add_fds > 32) {
535 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
536 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000537 }
Emeric Brun3854e012017-05-17 20:42:48 +0200538
539 /* We activate the polling for all known async fds */
540 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000541 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200542 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000543 /* To ensure that the fd cache won't be used
544 * We'll prefer to catch a real RD event
545 * because handling an EAGAIN on this fd will
546 * result in a context switch and also
547 * some engines uses a fd in blocking mode.
548 */
549 fd_cant_recv(add_fd[i]);
550 }
Emeric Brun3854e012017-05-17 20:42:48 +0200551
552 /* We must also prevent the conn_handler
553 * to be called until a read event was
554 * polled on an async fd
555 */
556 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000557}
558#endif
559
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200560/*
561 * This function returns the number of seconds elapsed
562 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
563 * date presented un ASN1_GENERALIZEDTIME.
564 *
565 * In parsing error case, it returns -1.
566 */
567static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
568{
569 long epoch;
570 char *p, *end;
571 const unsigned short month_offset[12] = {
572 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
573 };
574 int year, month;
575
576 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
577
578 p = (char *)d->data;
579 end = p + d->length;
580
581 if (end - p < 4) return -1;
582 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
583 p += 4;
584 if (end - p < 2) return -1;
585 month = 10 * (p[0] - '0') + p[1] - '0';
586 if (month < 1 || month > 12) return -1;
587 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
588 We consider leap years and the current month (<marsh or not) */
589 epoch = ( ((year - 1970) * 365)
590 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
591 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
592 + month_offset[month-1]
593 ) * 24 * 60 * 60;
594 p += 2;
595 if (end - p < 2) return -1;
596 /* Add the number of seconds of completed days of current month */
597 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
598 p += 2;
599 if (end - p < 2) return -1;
600 /* Add the completed hours of the current day */
601 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
602 p += 2;
603 if (end - p < 2) return -1;
604 /* Add the completed minutes of the current hour */
605 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
606 p += 2;
607 if (p == end) return -1;
608 /* Test if there is available seconds */
609 if (p[0] < '0' || p[0] > '9')
610 goto nosec;
611 if (end - p < 2) return -1;
612 /* Add the seconds of the current minute */
613 epoch += 10 * (p[0] - '0') + p[1] - '0';
614 p += 2;
615 if (p == end) return -1;
616 /* Ignore seconds float part if present */
617 if (p[0] == '.') {
618 do {
619 if (++p == end) return -1;
620 } while (p[0] >= '0' && p[0] <= '9');
621 }
622
623nosec:
624 if (p[0] == 'Z') {
625 if (end - p != 1) return -1;
626 return epoch;
627 }
628 else if (p[0] == '+') {
629 if (end - p != 5) return -1;
630 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700631 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 +0200632 }
633 else if (p[0] == '-') {
634 if (end - p != 5) return -1;
635 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700636 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 +0200637 }
638
639 return -1;
640}
641
Emeric Brun1d3865b2014-06-20 15:37:32 +0200642static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200643
644/* This function starts to check if the OCSP response (in DER format) contained
645 * in chunk 'ocsp_response' is valid (else exits on error).
646 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
647 * contained in the OCSP Response and exits on error if no match.
648 * If it's a valid OCSP Response:
649 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
650 * pointed by 'ocsp'.
651 * If 'ocsp' is NULL, the function looks up into the OCSP response's
652 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
653 * from the response) and exits on error if not found. Finally, If an OCSP response is
654 * already present in the container, it will be overwritten.
655 *
656 * Note: OCSP response containing more than one OCSP Single response is not
657 * considered valid.
658 *
659 * Returns 0 on success, 1 in error case.
660 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200661static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
662 struct certificate_ocsp *ocsp,
663 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200664{
665 OCSP_RESPONSE *resp;
666 OCSP_BASICRESP *bs = NULL;
667 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200668 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200669 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200670 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200671 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200672 int reason;
673 int ret = 1;
674
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200675 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
676 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200677 if (!resp) {
678 memprintf(err, "Unable to parse OCSP response");
679 goto out;
680 }
681
682 rc = OCSP_response_status(resp);
683 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
684 memprintf(err, "OCSP response status not successful");
685 goto out;
686 }
687
688 bs = OCSP_response_get1_basic(resp);
689 if (!bs) {
690 memprintf(err, "Failed to get basic response from OCSP Response");
691 goto out;
692 }
693
694 count_sr = OCSP_resp_count(bs);
695 if (count_sr > 1) {
696 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
697 goto out;
698 }
699
700 sr = OCSP_resp_get0(bs, 0);
701 if (!sr) {
702 memprintf(err, "Failed to get OCSP single response");
703 goto out;
704 }
705
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
707
Emeric Brun4147b2e2014-06-16 18:36:30 +0200708 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200709 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200710 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200711 goto out;
712 }
713
Emeric Brun13a6b482014-06-20 15:44:34 +0200714 if (!nextupd) {
715 memprintf(err, "OCSP single response: missing nextupdate");
716 goto out;
717 }
718
Emeric Brunc8b27b62014-06-19 14:16:17 +0200719 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200720 if (!rc) {
721 memprintf(err, "OCSP single response: no longer valid.");
722 goto out;
723 }
724
725 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200726 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200727 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
728 goto out;
729 }
730 }
731
732 if (!ocsp) {
733 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
734 unsigned char *p;
735
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200736 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200737 if (!rc) {
738 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
739 goto out;
740 }
741
742 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
743 memprintf(err, "OCSP single response: Certificate ID too long");
744 goto out;
745 }
746
747 p = key;
748 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200749 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
751 if (!ocsp) {
752 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
753 goto out;
754 }
755 }
756
757 /* According to comments on "chunk_dup", the
758 previous chunk buffer will be freed */
759 if (!chunk_dup(&ocsp->response, ocsp_response)) {
760 memprintf(err, "OCSP response: Memory allocation error");
761 goto out;
762 }
763
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200764 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
765
Emeric Brun4147b2e2014-06-16 18:36:30 +0200766 ret = 0;
767out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100768 ERR_clear_error();
769
Emeric Brun4147b2e2014-06-16 18:36:30 +0200770 if (bs)
771 OCSP_BASICRESP_free(bs);
772
773 if (resp)
774 OCSP_RESPONSE_free(resp);
775
776 return ret;
777}
778/*
779 * External function use to update the OCSP response in the OCSP response's
780 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
781 * to update in DER format.
782 *
783 * Returns 0 on success, 1 in error case.
784 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200785int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200786{
787 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
788}
789
790/*
791 * This function load the OCSP Resonse in DER format contained in file at
792 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
793 *
794 * Returns 0 on success, 1 in error case.
795 */
796static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
797{
798 int fd = -1;
799 int r = 0;
800 int ret = 1;
801
802 fd = open(ocsp_path, O_RDONLY);
803 if (fd == -1) {
804 memprintf(err, "Error opening OCSP response file");
805 goto end;
806 }
807
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200808 trash.data = 0;
809 while (trash.data < trash.size) {
810 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200811 if (r < 0) {
812 if (errno == EINTR)
813 continue;
814
815 memprintf(err, "Error reading OCSP response from file");
816 goto end;
817 }
818 else if (r == 0) {
819 break;
820 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200821 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200822 }
823
824 close(fd);
825 fd = -1;
826
827 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
828end:
829 if (fd != -1)
830 close(fd);
831
832 return ret;
833}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100834#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200835
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100836#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
837static 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)
838{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100839 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100840 struct tls_sess_key *keys;
841 struct connection *conn;
842 int head;
843 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100844 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100845
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200846 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200847 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100848 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
849
850 keys = ref->tlskeys;
851 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100852
853 if (enc) {
854 memcpy(key_name, keys[head].name, 16);
855
856 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100857 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100858
859 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100860 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100861
862 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100863 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100864 } else {
865 for (i = 0; i < TLS_TICKETS_NO; i++) {
866 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
867 goto found;
868 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100869 ret = 0;
870 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100871
Christopher Faulet16f45c82018-02-16 11:23:49 +0100872 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100873 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
874 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 +0100875 goto end;
876
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100877 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100878 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100879 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100880 end:
881 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
882 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200883}
884
885struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
886{
887 struct tls_keys_ref *ref;
888
889 list_for_each_entry(ref, &tlskeys_reference, list)
890 if (ref->filename && strcmp(filename, ref->filename) == 0)
891 return ref;
892 return NULL;
893}
894
895struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
896{
897 struct tls_keys_ref *ref;
898
899 list_for_each_entry(ref, &tlskeys_reference, list)
900 if (ref->unique_id == unique_id)
901 return ref;
902 return NULL;
903}
904
Willy Tarreau83061a82018-07-13 11:56:34 +0200905void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
906 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100907{
908 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200909 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
910 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100911 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
912 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
913}
914
Willy Tarreau83061a82018-07-13 11:56:34 +0200915int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100916{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200917 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
918
919 if(!ref) {
920 memprintf(err, "Unable to locate the referenced filename: %s", filename);
921 return 1;
922 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100923 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200924 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100925}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200926
927/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100928 * automatic ids. It's called just after the basic checks. It returns
929 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200930 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100931static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200932{
933 int i = 0;
934 struct tls_keys_ref *ref, *ref2, *ref3;
935 struct list tkr = LIST_HEAD_INIT(tkr);
936
937 list_for_each_entry(ref, &tlskeys_reference, list) {
938 if (ref->unique_id == -1) {
939 /* Look for the first free id. */
940 while (1) {
941 list_for_each_entry(ref2, &tlskeys_reference, list) {
942 if (ref2->unique_id == i) {
943 i++;
944 break;
945 }
946 }
947 if (&ref2->list == &tlskeys_reference)
948 break;
949 }
950
951 /* Uses the unique id and increment it for the next entry. */
952 ref->unique_id = i;
953 i++;
954 }
955 }
956
957 /* This sort the reference list by id. */
958 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
959 LIST_DEL(&ref->list);
960 list_for_each_entry(ref3, &tkr, list) {
961 if (ref->unique_id < ref3->unique_id) {
962 LIST_ADDQ(&ref3->list, &ref->list);
963 break;
964 }
965 }
966 if (&ref3->list == &tkr)
967 LIST_ADDQ(&tkr, &ref->list);
968 }
969
970 /* swap root */
971 LIST_ADD(&tkr, &tlskeys_reference);
972 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100973 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200974}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
976
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100977#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500978int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
979{
980 switch (evp_keytype) {
981 case EVP_PKEY_RSA:
982 return 2;
983 case EVP_PKEY_DSA:
984 return 0;
985 case EVP_PKEY_EC:
986 return 1;
987 }
988
989 return -1;
990}
991
Emeric Brun4147b2e2014-06-16 18:36:30 +0200992/*
993 * Callback used to set OCSP status extension content in server hello.
994 */
995int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
996{
yanbzhube2774d2015-12-10 15:07:30 -0500997 struct certificate_ocsp *ocsp;
998 struct ocsp_cbk_arg *ocsp_arg;
999 char *ssl_buf;
1000 EVP_PKEY *ssl_pkey;
1001 int key_type;
1002 int index;
1003
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001004 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001005
1006 ssl_pkey = SSL_get_privatekey(ssl);
1007 if (!ssl_pkey)
1008 return SSL_TLSEXT_ERR_NOACK;
1009
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001010 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001011
1012 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1013 ocsp = ocsp_arg->s_ocsp;
1014 else {
1015 /* For multiple certs per context, we have to find the correct OCSP response based on
1016 * the certificate type
1017 */
1018 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1019
1020 if (index < 0)
1021 return SSL_TLSEXT_ERR_NOACK;
1022
1023 ocsp = ocsp_arg->m_ocsp[index];
1024
1025 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001026
1027 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001028 !ocsp->response.area ||
1029 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001031 return SSL_TLSEXT_ERR_NOACK;
1032
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001033 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001034 if (!ssl_buf)
1035 return SSL_TLSEXT_ERR_NOACK;
1036
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001037 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1038 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039
1040 return SSL_TLSEXT_ERR_OK;
1041}
1042
1043/*
1044 * This function enables the handling of OCSP status extension on 'ctx' if a
1045 * file name 'cert_path' suffixed using ".ocsp" is present.
1046 * To enable OCSP status extension, the issuer's certificate is mandatory.
1047 * It should be present in the certificate's extra chain builded from file
1048 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1049 * named 'cert_path' suffixed using '.issuer'.
1050 *
1051 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1052 * response. If file is empty or content is not a valid OCSP response,
1053 * OCSP status extension is enabled but OCSP response is ignored (a warning
1054 * is displayed).
1055 *
1056 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001057 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001058 */
1059static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1060{
1061
1062 BIO *in = NULL;
1063 X509 *x, *xi = NULL, *issuer = NULL;
1064 STACK_OF(X509) *chain = NULL;
1065 OCSP_CERTID *cid = NULL;
1066 SSL *ssl;
1067 char ocsp_path[MAXPATHLEN+1];
1068 int i, ret = -1;
1069 struct stat st;
1070 struct certificate_ocsp *ocsp = NULL, *iocsp;
1071 char *warn = NULL;
1072 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001073 pem_password_cb *passwd_cb;
1074 void *passwd_cb_userdata;
1075 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
1077 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1078
1079 if (stat(ocsp_path, &st))
1080 return 1;
1081
1082 ssl = SSL_new(ctx);
1083 if (!ssl)
1084 goto out;
1085
1086 x = SSL_get_certificate(ssl);
1087 if (!x)
1088 goto out;
1089
1090 /* Try to lookup for issuer in certificate extra chain */
1091#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1092 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1093#else
1094 chain = ctx->extra_certs;
1095#endif
1096 for (i = 0; i < sk_X509_num(chain); i++) {
1097 issuer = sk_X509_value(chain, i);
1098 if (X509_check_issued(issuer, x) == X509_V_OK)
1099 break;
1100 else
1101 issuer = NULL;
1102 }
1103
1104 /* If not found try to load issuer from a suffixed file */
1105 if (!issuer) {
1106 char issuer_path[MAXPATHLEN+1];
1107
1108 in = BIO_new(BIO_s_file());
1109 if (!in)
1110 goto out;
1111
1112 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1113 if (BIO_read_filename(in, issuer_path) <= 0)
1114 goto out;
1115
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001116 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1117 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1118
1119 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001120 if (!xi)
1121 goto out;
1122
1123 if (X509_check_issued(xi, x) != X509_V_OK)
1124 goto out;
1125
1126 issuer = xi;
1127 }
1128
1129 cid = OCSP_cert_to_id(0, x, issuer);
1130 if (!cid)
1131 goto out;
1132
1133 i = i2d_OCSP_CERTID(cid, NULL);
1134 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1135 goto out;
1136
Vincent Bernat02779b62016-04-03 13:48:43 +02001137 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001138 if (!ocsp)
1139 goto out;
1140
1141 p = ocsp->key_data;
1142 i2d_OCSP_CERTID(cid, &p);
1143
1144 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1145 if (iocsp == ocsp)
1146 ocsp = NULL;
1147
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001148#ifndef SSL_CTX_get_tlsext_status_cb
1149# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1150 *cb = (void (*) (void))ctx->tlsext_status_cb;
1151#endif
1152 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1153
1154 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001155 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001156 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001157
1158 cb_arg->is_single = 1;
1159 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001160
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001161 pkey = X509_get_pubkey(x);
1162 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1163 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001164
1165 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1166 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1167 } else {
1168 /*
1169 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1170 * Update that cb_arg with the new cert's staple
1171 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001172 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001173 struct certificate_ocsp *tmp_ocsp;
1174 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001175 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001176 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001177
1178#ifdef SSL_CTX_get_tlsext_status_arg
1179 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1180#else
1181 cb_arg = ctx->tlsext_status_arg;
1182#endif
yanbzhube2774d2015-12-10 15:07:30 -05001183
1184 /*
1185 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1186 * the order of operations below matter, take care when changing it
1187 */
1188 tmp_ocsp = cb_arg->s_ocsp;
1189 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1190 cb_arg->s_ocsp = NULL;
1191 cb_arg->m_ocsp[index] = tmp_ocsp;
1192 cb_arg->is_single = 0;
1193 cb_arg->single_kt = 0;
1194
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001195 pkey = X509_get_pubkey(x);
1196 key_type = EVP_PKEY_base_id(pkey);
1197 EVP_PKEY_free(pkey);
1198
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001199 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001200 if (index >= 0 && !cb_arg->m_ocsp[index])
1201 cb_arg->m_ocsp[index] = iocsp;
1202
1203 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001204
1205 ret = 0;
1206
1207 warn = NULL;
1208 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1209 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001210 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001211 }
1212
1213out:
1214 if (ssl)
1215 SSL_free(ssl);
1216
1217 if (in)
1218 BIO_free(in);
1219
1220 if (xi)
1221 X509_free(xi);
1222
1223 if (cid)
1224 OCSP_CERTID_free(cid);
1225
1226 if (ocsp)
1227 free(ocsp);
1228
1229 if (warn)
1230 free(warn);
1231
1232
1233 return ret;
1234}
1235
1236#endif
1237
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001238#ifdef OPENSSL_IS_BORINGSSL
1239static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1240{
1241 char ocsp_path[MAXPATHLEN+1];
1242 struct stat st;
1243 int fd = -1, r = 0;
1244
1245 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1246 if (stat(ocsp_path, &st))
1247 return 0;
1248
1249 fd = open(ocsp_path, O_RDONLY);
1250 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001251 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001252 return -1;
1253 }
1254
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001255 trash.data = 0;
1256 while (trash.data < trash.size) {
1257 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001258 if (r < 0) {
1259 if (errno == EINTR)
1260 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001261 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001262 close(fd);
1263 return -1;
1264 }
1265 else if (r == 0) {
1266 break;
1267 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001268 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001269 }
1270 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001271 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1272 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001273}
1274#endif
1275
Daniel Jakots54ffb912015-11-06 20:02:41 +01001276#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001277
1278#define CT_EXTENSION_TYPE 18
1279
1280static int sctl_ex_index = -1;
1281
1282/*
1283 * Try to parse Signed Certificate Timestamp List structure. This function
1284 * makes only basic test if the data seems like SCTL. No signature validation
1285 * is performed.
1286 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001287static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001288{
1289 int ret = 1;
1290 int len, pos, sct_len;
1291 unsigned char *data;
1292
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001293 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001294 goto out;
1295
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001296 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001297 len = (data[0] << 8) | data[1];
1298
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001299 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001300 goto out;
1301
1302 data = data + 2;
1303 pos = 0;
1304 while (pos < len) {
1305 if (len - pos < 2)
1306 goto out;
1307
1308 sct_len = (data[pos] << 8) | data[pos + 1];
1309 if (pos + sct_len + 2 > len)
1310 goto out;
1311
1312 pos += sct_len + 2;
1313 }
1314
1315 ret = 0;
1316
1317out:
1318 return ret;
1319}
1320
Willy Tarreau83061a82018-07-13 11:56:34 +02001321static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1322 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001323{
1324 int fd = -1;
1325 int r = 0;
1326 int ret = 1;
1327
1328 *sctl = NULL;
1329
1330 fd = open(sctl_path, O_RDONLY);
1331 if (fd == -1)
1332 goto end;
1333
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001334 trash.data = 0;
1335 while (trash.data < trash.size) {
1336 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001337 if (r < 0) {
1338 if (errno == EINTR)
1339 continue;
1340
1341 goto end;
1342 }
1343 else if (r == 0) {
1344 break;
1345 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001346 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001347 }
1348
1349 ret = ssl_sock_parse_sctl(&trash);
1350 if (ret)
1351 goto end;
1352
Vincent Bernat02779b62016-04-03 13:48:43 +02001353 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001354 if (!chunk_dup(*sctl, &trash)) {
1355 free(*sctl);
1356 *sctl = NULL;
1357 goto end;
1358 }
1359
1360end:
1361 if (fd != -1)
1362 close(fd);
1363
1364 return ret;
1365}
1366
1367int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1368{
Willy Tarreau83061a82018-07-13 11:56:34 +02001369 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001370
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001371 *out = (unsigned char *) sctl->area;
1372 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001373
1374 return 1;
1375}
1376
1377int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1378{
1379 return 1;
1380}
1381
1382static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1383{
1384 char sctl_path[MAXPATHLEN+1];
1385 int ret = -1;
1386 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001387 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001388
1389 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1390
1391 if (stat(sctl_path, &st))
1392 return 1;
1393
1394 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1395 goto out;
1396
1397 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1398 free(sctl);
1399 goto out;
1400 }
1401
1402 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1403
1404 ret = 0;
1405
1406out:
1407 return ret;
1408}
1409
1410#endif
1411
Emeric Brune1f38db2012-09-03 20:36:47 +02001412void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1413{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001414 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001415 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001416 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001417
1418 if (where & SSL_CB_HANDSHAKE_START) {
1419 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001420 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 +02001421 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001422 conn->err_code = CO_ER_SSL_RENEG;
1423 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001424 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001425
1426 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1427 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1428 /* Long certificate chains optimz
1429 If write and read bios are differents, we
1430 consider that the buffering was activated,
1431 so we rise the output buffer size from 4k
1432 to 16k */
1433 write_bio = SSL_get_wbio(ssl);
1434 if (write_bio != SSL_get_rbio(ssl)) {
1435 BIO_set_write_buffer_size(write_bio, 16384);
1436 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1437 }
1438 }
1439 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001440}
1441
Emeric Brune64aef12012-09-21 13:15:06 +02001442/* Callback is called for each certificate of the chain during a verify
1443 ok is set to 1 if preverify detect no error on current certificate.
1444 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001445int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001446{
1447 SSL *ssl;
1448 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001449 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001450
1451 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001452 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001453
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001454 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001455
Emeric Brun81c00f02012-09-21 14:31:21 +02001456 if (ok) /* no errors */
1457 return ok;
1458
1459 depth = X509_STORE_CTX_get_error_depth(x_store);
1460 err = X509_STORE_CTX_get_error(x_store);
1461
1462 /* check if CA error needs to be ignored */
1463 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001464 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1465 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1466 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001467 }
1468
Willy Tarreau07d94e42018-09-20 10:57:52 +02001469 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001470 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001471 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001472 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001473 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001474
Willy Tarreau20879a02012-12-03 16:32:10 +01001475 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001476 return 0;
1477 }
1478
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001479 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1480 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001481
Emeric Brun81c00f02012-09-21 14:31:21 +02001482 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001483 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001484 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001485 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001486 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001487 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001488
Willy Tarreau20879a02012-12-03 16:32:10 +01001489 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001490 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001491}
1492
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001493static inline
1494void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001495 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001496{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001497 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001498 unsigned char *msg;
1499 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001500 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001501
1502 /* This function is called for "from client" and "to server"
1503 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001504 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001505 */
1506
1507 /* "write_p" is set to 0 is the bytes are received messages,
1508 * otherwise it is set to 1.
1509 */
1510 if (write_p != 0)
1511 return;
1512
1513 /* content_type contains the type of message received or sent
1514 * according with the SSL/TLS protocol spec. This message is
1515 * encoded with one byte. The value 256 (two bytes) is used
1516 * for designing the SSL/TLS record layer. According with the
1517 * rfc6101, the expected message (other than 256) are:
1518 * - change_cipher_spec(20)
1519 * - alert(21)
1520 * - handshake(22)
1521 * - application_data(23)
1522 * - (255)
1523 * We are interessed by the handshake and specially the client
1524 * hello.
1525 */
1526 if (content_type != 22)
1527 return;
1528
1529 /* The message length is at least 4 bytes, containing the
1530 * message type and the message length.
1531 */
1532 if (len < 4)
1533 return;
1534
1535 /* First byte of the handshake message id the type of
1536 * message. The konwn types are:
1537 * - hello_request(0)
1538 * - client_hello(1)
1539 * - server_hello(2)
1540 * - certificate(11)
1541 * - server_key_exchange (12)
1542 * - certificate_request(13)
1543 * - server_hello_done(14)
1544 * We are interested by the client hello.
1545 */
1546 msg = (unsigned char *)buf;
1547 if (msg[0] != 1)
1548 return;
1549
1550 /* Next three bytes are the length of the message. The total length
1551 * must be this decoded length + 4. If the length given as argument
1552 * is not the same, we abort the protocol dissector.
1553 */
1554 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1555 if (len < rec_len + 4)
1556 return;
1557 msg += 4;
1558 end = msg + rec_len;
1559 if (end < msg)
1560 return;
1561
1562 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1563 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001564 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1565 */
1566 msg += 1 + 1 + 4 + 28;
1567 if (msg > end)
1568 return;
1569
1570 /* Next, is session id:
1571 * if present, we have to jump by length + 1 for the size information
1572 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001573 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001574 if (msg[0] > 0)
1575 msg += msg[0];
1576 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001577 if (msg > end)
1578 return;
1579
1580 /* Next two bytes are the ciphersuite length. */
1581 if (msg + 2 > end)
1582 return;
1583 rec_len = (msg[0] << 8) + msg[1];
1584 msg += 2;
1585 if (msg + rec_len > end || msg + rec_len < msg)
1586 return;
1587
Willy Tarreaubafbe012017-11-24 17:34:44 +01001588 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001589 if (!capture)
1590 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001591 /* Compute the xxh64 of the ciphersuite. */
1592 capture->xxh64 = XXH64(msg, rec_len, 0);
1593
1594 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001595 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1596 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001597 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001598
1599 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001600}
1601
Emeric Brun29f037d2014-04-25 19:05:36 +02001602/* Callback is called for ssl protocol analyse */
1603void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1604{
Emeric Brun29f037d2014-04-25 19:05:36 +02001605#ifdef TLS1_RT_HEARTBEAT
1606 /* test heartbeat received (write_p is set to 0
1607 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001608 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001609 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001610 const unsigned char *p = buf;
1611 unsigned int payload;
1612
Emeric Brun29f037d2014-04-25 19:05:36 +02001613 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001614
1615 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1616 if (*p != TLS1_HB_REQUEST)
1617 return;
1618
Willy Tarreauaeed6722014-04-25 23:59:58 +02001619 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001620 goto kill_it;
1621
1622 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001623 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001624 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001625 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001626 /* We have a clear heartbleed attack (CVE-2014-0160), the
1627 * advertised payload is larger than the advertised packet
1628 * length, so we have garbage in the buffer between the
1629 * payload and the end of the buffer (p+len). We can't know
1630 * if the SSL stack is patched, and we don't know if we can
1631 * safely wipe out the area between p+3+len and payload.
1632 * So instead, we prevent the response from being sent by
1633 * setting the max_send_fragment to 0 and we report an SSL
1634 * error, which will kill this connection. It will be reported
1635 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001636 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1637 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001638 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001639 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1640 return;
1641 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001642#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001643 if (global_ssl.capture_cipherlist > 0)
1644 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001645}
1646
Bernard Spil13c53f82018-02-15 13:34:58 +01001647#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001648static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1649 const unsigned char *in, unsigned int inlen,
1650 void *arg)
1651{
1652 struct server *srv = arg;
1653
1654 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1655 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1656 return SSL_TLSEXT_ERR_OK;
1657 return SSL_TLSEXT_ERR_NOACK;
1658}
1659#endif
1660
1661#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001662/* This callback is used so that the server advertises the list of
1663 * negociable protocols for NPN.
1664 */
1665static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1666 unsigned int *len, void *arg)
1667{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001668 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001669
1670 *data = (const unsigned char *)conf->npn_str;
1671 *len = conf->npn_len;
1672 return SSL_TLSEXT_ERR_OK;
1673}
1674#endif
1675
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001676#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001677/* This callback is used so that the server advertises the list of
1678 * negociable protocols for ALPN.
1679 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001680static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1681 unsigned char *outlen,
1682 const unsigned char *server,
1683 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001684{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001685 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001686
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001687 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1688 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1689 return SSL_TLSEXT_ERR_NOACK;
1690 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001691 return SSL_TLSEXT_ERR_OK;
1692}
1693#endif
1694
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001695#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001696#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001697
Christopher Faulet30548802015-06-11 13:39:32 +02001698/* Create a X509 certificate with the specified servername and serial. This
1699 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001700static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001701ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001702{
Christopher Faulet7969a332015-10-09 11:15:03 +02001703 X509 *cacert = bind_conf->ca_sign_cert;
1704 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001705 SSL_CTX *ssl_ctx = NULL;
1706 X509 *newcrt = NULL;
1707 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001708 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001709 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001710 X509_NAME *name;
1711 const EVP_MD *digest;
1712 X509V3_CTX ctx;
1713 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001714 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001715
Christopher Faulet48a83322017-07-28 16:56:09 +02001716 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001717#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1718 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1719#else
1720 tmp_ssl = SSL_new(bind_conf->default_ctx);
1721 if (tmp_ssl)
1722 pkey = SSL_get_privatekey(tmp_ssl);
1723#endif
1724 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001725 goto mkcert_error;
1726
1727 /* Create the certificate */
1728 if (!(newcrt = X509_new()))
1729 goto mkcert_error;
1730
1731 /* Set version number for the certificate (X509v3) and the serial
1732 * number */
1733 if (X509_set_version(newcrt, 2L) != 1)
1734 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001735 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001736
1737 /* Set duration for the certificate */
1738 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1739 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1740 goto mkcert_error;
1741
1742 /* set public key in the certificate */
1743 if (X509_set_pubkey(newcrt, pkey) != 1)
1744 goto mkcert_error;
1745
1746 /* Set issuer name from the CA */
1747 if (!(name = X509_get_subject_name(cacert)))
1748 goto mkcert_error;
1749 if (X509_set_issuer_name(newcrt, name) != 1)
1750 goto mkcert_error;
1751
1752 /* Set the subject name using the same, but the CN */
1753 name = X509_NAME_dup(name);
1754 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1755 (const unsigned char *)servername,
1756 -1, -1, 0) != 1) {
1757 X509_NAME_free(name);
1758 goto mkcert_error;
1759 }
1760 if (X509_set_subject_name(newcrt, name) != 1) {
1761 X509_NAME_free(name);
1762 goto mkcert_error;
1763 }
1764 X509_NAME_free(name);
1765
1766 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001767 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001768 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1769 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1770 X509_EXTENSION *ext;
1771
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001772 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 goto mkcert_error;
1774 if (!X509_add_ext(newcrt, ext, -1)) {
1775 X509_EXTENSION_free(ext);
1776 goto mkcert_error;
1777 }
1778 X509_EXTENSION_free(ext);
1779 }
1780
1781 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001782
1783 key_type = EVP_PKEY_base_id(capkey);
1784
1785 if (key_type == EVP_PKEY_DSA)
1786 digest = EVP_sha1();
1787 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001788 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001789 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001790 digest = EVP_sha256();
1791 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001792#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001793 int nid;
1794
1795 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1796 goto mkcert_error;
1797 if (!(digest = EVP_get_digestbynid(nid)))
1798 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001799#else
1800 goto mkcert_error;
1801#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001802 }
1803
Christopher Faulet31af49d2015-06-09 17:29:50 +02001804 if (!(X509_sign(newcrt, capkey, digest)))
1805 goto mkcert_error;
1806
1807 /* Create and set the new SSL_CTX */
1808 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1809 goto mkcert_error;
1810 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1811 goto mkcert_error;
1812 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1813 goto mkcert_error;
1814 if (!SSL_CTX_check_private_key(ssl_ctx))
1815 goto mkcert_error;
1816
1817 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001818
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001819#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001820 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001821#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001822#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1823 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001824 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001825 EC_KEY *ecc;
1826 int nid;
1827
1828 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1829 goto end;
1830 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1831 goto end;
1832 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1833 EC_KEY_free(ecc);
1834 }
1835#endif
1836 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001837 return ssl_ctx;
1838
1839 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001840 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001841 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001842 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1843 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001844 return NULL;
1845}
1846
Christopher Faulet7969a332015-10-09 11:15:03 +02001847SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001848ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001849{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001850 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001851
1852 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001853}
1854
Christopher Faulet30548802015-06-11 13:39:32 +02001855/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001856 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001857SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001858ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001859{
1860 struct lru64 *lru = NULL;
1861
1862 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001863 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001864 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001865 if (lru && lru->domain) {
1866 if (ssl)
1867 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001868 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001869 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001870 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001871 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001872 }
1873 return NULL;
1874}
1875
Emeric Brun821bb9b2017-06-15 16:37:39 +02001876/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1877 * function is not thread-safe, it should only be used to check if a certificate
1878 * exists in the lru cache (with no warranty it will not be removed by another
1879 * thread). It is kept for backward compatibility. */
1880SSL_CTX *
1881ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1882{
1883 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1884}
1885
Christopher Fauletd2cab922015-07-28 16:03:47 +02001886/* Set a certificate int the LRU cache used to store generated
1887 * certificate. Return 0 on success, otherwise -1 */
1888int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001889ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001890{
1891 struct lru64 *lru = NULL;
1892
1893 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001894 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001895 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001896 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001897 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001898 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001899 }
Christopher Faulet30548802015-06-11 13:39:32 +02001900 if (lru->domain && lru->data)
1901 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001902 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001903 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001904 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001905 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001906 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001907}
1908
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001909/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001910unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001911ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001912{
1913 return XXH32(data, len, ssl_ctx_lru_seed);
1914}
1915
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001916/* Generate a cert and immediately assign it to the SSL session so that the cert's
1917 * refcount is maintained regardless of the cert's presence in the LRU cache.
1918 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001919static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001920ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001921{
1922 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001923 SSL_CTX *ssl_ctx = NULL;
1924 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001925 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001927 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001928 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001929 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001930 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001931 if (lru && lru->domain)
1932 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001933 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001934 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001935 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001936 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001937 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001938 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001939 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001940 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001941 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001942 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001943 SSL_set_SSL_CTX(ssl, ssl_ctx);
1944 /* No LRU cache, this CTX will be released as soon as the session dies */
1945 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001946 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001947 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001948 return 0;
1949}
1950static int
1951ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1952{
1953 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001954 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001955
1956 conn_get_to_addr(conn);
1957 if (conn->flags & CO_FL_ADDR_TO_SET) {
1958 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001959 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001960 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001961 }
1962 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001963}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001964#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001965
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966
1967#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1968#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1969#endif
1970
1971#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1972#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1973#define SSL_renegotiate_pending(arg) 0
1974#endif
1975#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1976#define SSL_OP_SINGLE_ECDH_USE 0
1977#endif
1978#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1979#define SSL_OP_NO_TICKET 0
1980#endif
1981#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1982#define SSL_OP_NO_COMPRESSION 0
1983#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001984#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1985#undef SSL_OP_NO_SSLv3
1986#define SSL_OP_NO_SSLv3 0
1987#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001988#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1989#define SSL_OP_NO_TLSv1_1 0
1990#endif
1991#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1992#define SSL_OP_NO_TLSv1_2 0
1993#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001994#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001995#define SSL_OP_NO_TLSv1_3 0
1996#endif
1997#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1998#define SSL_OP_SINGLE_DH_USE 0
1999#endif
2000#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
2001#define SSL_OP_SINGLE_ECDH_USE 0
2002#endif
2003#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
2004#define SSL_MODE_RELEASE_BUFFERS 0
2005#endif
2006#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
2007#define SSL_MODE_SMALL_BUFFERS 0
2008#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02002009#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2010#define SSL_OP_PRIORITIZE_CHACHA 0
2011#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002013#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2015
2016static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002018#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2021#endif
2022}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002023static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2024 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2026}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002027static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002029 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002030 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2031#endif
2032}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002034#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002036 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2037#endif
2038}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002039/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002040static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2041/* Unusable in this context. */
2042static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2043static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2044static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2045static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2046static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002047#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002048typedef enum { SET_MIN, SET_MAX } set_context_func;
2049
2050static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2051 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002052 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2053}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2055 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2056 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2057}
2058static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2059 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002060 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2061}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002062static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2063 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2064 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2065}
2066static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2067 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002068 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2069}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002070static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2071 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2072 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2073}
2074static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2075 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002076 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2077}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002078static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2079 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2080 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2081}
2082static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002084 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002085 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2086#endif
2087}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002088static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2089#if SSL_OP_NO_TLSv1_3
2090 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2091 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002092#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002093}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002094#endif
2095static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2096static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002097
2098static struct {
2099 int option;
2100 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002101 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2102 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002103 const char *name;
2104} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002105 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2106 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2107 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2108 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2109 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2110 {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 +02002111};
2112
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002113static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2114{
2115 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2116 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2117 SSL_set_SSL_CTX(ssl, ctx);
2118}
2119
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002120#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121
2122static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2123{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002124 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002126
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002127 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2128 return SSL_TLSEXT_ERR_OK;
2129 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002130}
2131
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002132#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002133static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2134{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002135 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002136#else
2137static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2138{
2139#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 struct connection *conn;
2141 struct bind_conf *s;
2142 const uint8_t *extension_data;
2143 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002144 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002145
2146 char *wildp = NULL;
2147 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002148 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002149 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002150 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002151 int i;
2152
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002153 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002154 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002155
Olivier Houchard9679ac92017-10-27 14:58:08 +02002156 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002157 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002158#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002159 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2160 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002161#else
2162 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2163#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002164 /*
2165 * The server_name extension was given too much extensibility when it
2166 * was written, so parsing the normal case is a bit complex.
2167 */
2168 size_t len;
2169 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002170 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002171 /* Extract the length of the supplied list of names. */
2172 len = (*extension_data++) << 8;
2173 len |= *extension_data++;
2174 if (len + 2 != extension_len)
2175 goto abort;
2176 /*
2177 * The list in practice only has a single element, so we only consider
2178 * the first one.
2179 */
2180 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2181 goto abort;
2182 extension_len = len - 1;
2183 /* Now we can finally pull out the byte array with the actual hostname. */
2184 if (extension_len <= 2)
2185 goto abort;
2186 len = (*extension_data++) << 8;
2187 len |= *extension_data++;
2188 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2189 || memchr(extension_data, 0, len) != NULL)
2190 goto abort;
2191 servername = extension_data;
2192 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002193 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002194#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2195 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002196 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002197 }
2198#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002200 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002202 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002203 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002204 goto abort;
2205 }
2206
2207 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002208#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002209 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002210#else
2211 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2212#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002213 uint8_t sign;
2214 size_t len;
2215 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002216 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002217 len = (*extension_data++) << 8;
2218 len |= *extension_data++;
2219 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002221 if (len % 2 != 0)
2222 goto abort;
2223 for (; len > 0; len -= 2) {
2224 extension_data++; /* hash */
2225 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002226 switch (sign) {
2227 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002228 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002229 break;
2230 case TLSEXT_signature_ecdsa:
2231 has_ecdsa_sig = 1;
2232 break;
2233 default:
2234 continue;
2235 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002236 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 break;
2238 }
2239 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002240 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002241 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002242 }
2243 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 const SSL_CIPHER *cipher;
2245 size_t len;
2246 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002247 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002248#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 len = ctx->cipher_suites_len;
2250 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002251#else
2252 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2253#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002254 if (len % 2 != 0)
2255 goto abort;
2256 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002257#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002258 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002259 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002260#else
2261 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2262#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002263 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002264 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 break;
2266 }
2267 }
2268 }
2269
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002270 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002271 trash.area[i] = tolower(servername[i]);
2272 if (!wildp && (trash.area[i] == '.'))
2273 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002274 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002275 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276
2277 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002278 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002279
2280 /* lookup a not neg filter */
2281 for (n = node; n; n = ebmb_next_dup(n)) {
2282 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002283 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002285 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002286 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 break;
2288 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002289 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002290 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002291 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002292 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002293 if (!node_anonymous)
2294 node_anonymous = n;
2295 break;
2296 }
2297 }
2298 }
2299 if (wildp) {
2300 /* lookup in wildcards names */
2301 node = ebst_lookup(&s->sni_w_ctx, wildp);
2302 for (n = node; n; n = ebmb_next_dup(n)) {
2303 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002304 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002306 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002308 break;
2309 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002310 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002311 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002312 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002313 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002314 if (!node_anonymous)
2315 node_anonymous = n;
2316 break;
2317 }
2318 }
2319 }
2320 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002321 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002322 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2323 : ((has_rsa_sig && node_rsa) ? node_rsa
2324 : (node_anonymous ? node_anonymous
2325 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2326 : node_rsa /* no rsa signature case (far far away) */
2327 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002328 if (node) {
2329 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002330 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002331 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002332 if (conf) {
2333 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2334 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2335 if (conf->early_data)
2336 allow_early = 1;
2337 }
2338 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002339 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002340#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002341 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002342 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002343 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002344 }
2345#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002346 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002348 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002349 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002350allow_early:
2351#ifdef OPENSSL_IS_BORINGSSL
2352 if (allow_early)
2353 SSL_set_early_data_enabled(ssl, 1);
2354#else
2355 if (!allow_early)
2356 SSL_set_max_early_data(ssl, 0);
2357#endif
2358 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 abort:
2360 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2361 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002362#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002363 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002364#else
2365 *al = SSL_AD_UNRECOGNIZED_NAME;
2366 return 0;
2367#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002368}
2369
2370#else /* OPENSSL_IS_BORINGSSL */
2371
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2373 * warning when no match is found, which implies the default (first) cert
2374 * will keep being used.
2375 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002376static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002377{
2378 const char *servername;
2379 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002380 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002381 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002382 int i;
2383 (void)al; /* shut gcc stupid warning */
2384
2385 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002386 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002387#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002388 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2389 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002390#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002391 if (s->strict_sni)
2392 return SSL_TLSEXT_ERR_ALERT_FATAL;
2393 ssl_sock_switchctx_set(ssl, s->default_ctx);
2394 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002395 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002396
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002397 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002398 if (!servername[i])
2399 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002400 trash.area[i] = tolower(servername[i]);
2401 if (!wildp && (trash.area[i] == '.'))
2402 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002403 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002404 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002405
2406 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002407 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002408
2409 /* lookup a not neg filter */
2410 for (n = node; n; n = ebmb_next_dup(n)) {
2411 if (!container_of(n, struct sni_ctx, name)->neg) {
2412 node = n;
2413 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002414 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002415 }
2416 if (!node && wildp) {
2417 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002418 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002419 }
2420 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002422 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2423 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002424 return SSL_TLSEXT_ERR_OK;
2425 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002426#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002427 if (s->strict_sni)
2428 return SSL_TLSEXT_ERR_ALERT_FATAL;
2429 ssl_sock_switchctx_set(ssl, s->default_ctx);
2430 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002431 }
2432
2433 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002434 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002435 return SSL_TLSEXT_ERR_OK;
2436}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002437#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002438#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2439
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002440#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002441
2442static DH * ssl_get_dh_1024(void)
2443{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002444 static unsigned char dh1024_p[]={
2445 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2446 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2447 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2448 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2449 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2450 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2451 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2452 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2453 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2454 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2455 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2456 };
2457 static unsigned char dh1024_g[]={
2458 0x02,
2459 };
2460
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002461 BIGNUM *p;
2462 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002463 DH *dh = DH_new();
2464 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002465 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2466 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002467
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002469 DH_free(dh);
2470 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002471 } else {
2472 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002473 }
2474 }
2475 return dh;
2476}
2477
2478static DH *ssl_get_dh_2048(void)
2479{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002480 static unsigned char dh2048_p[]={
2481 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2482 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2483 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2484 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2485 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2486 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2487 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2488 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2489 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2490 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2491 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2492 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2493 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2494 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2495 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2496 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2497 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2498 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2499 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2500 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2501 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2502 0xB7,0x1F,0x77,0xF3,
2503 };
2504 static unsigned char dh2048_g[]={
2505 0x02,
2506 };
2507
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002508 BIGNUM *p;
2509 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002510 DH *dh = DH_new();
2511 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002512 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2513 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002514
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002515 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002516 DH_free(dh);
2517 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 } else {
2519 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002520 }
2521 }
2522 return dh;
2523}
2524
2525static DH *ssl_get_dh_4096(void)
2526{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002527 static unsigned char dh4096_p[]={
2528 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2529 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2530 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2531 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2532 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2533 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2534 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2535 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2536 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2537 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2538 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2539 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2540 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2541 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2542 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2543 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2544 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2545 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2546 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2547 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2548 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2549 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2550 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2551 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2552 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2553 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2554 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2555 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2556 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2557 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2558 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2559 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2560 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2561 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2562 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2563 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2564 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2565 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2566 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2567 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2568 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2569 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2570 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002571 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002572 static unsigned char dh4096_g[]={
2573 0x02,
2574 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002575
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002576 BIGNUM *p;
2577 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 DH *dh = DH_new();
2579 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002580 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2581 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002582
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002583 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002584 DH_free(dh);
2585 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002586 } else {
2587 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002588 }
2589 }
2590 return dh;
2591}
2592
2593/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002594 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002595static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2596{
2597 DH *dh = NULL;
2598 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002599 int type;
2600
2601 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002602
2603 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2604 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2605 */
2606 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2607 keylen = EVP_PKEY_bits(pkey);
2608 }
2609
Willy Tarreauef934602016-12-22 23:12:01 +01002610 if (keylen > global_ssl.default_dh_param) {
2611 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002612 }
2613
Remi Gacogned3a341a2015-05-29 16:26:17 +02002614 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002615 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002616 }
2617 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002618 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002619 }
2620 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002621 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 }
2623
2624 return dh;
2625}
2626
Remi Gacogne47783ef2015-05-29 15:53:22 +02002627static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002628{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002629 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002630 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002631
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002632 if (in == NULL)
2633 goto end;
2634
Remi Gacogne47783ef2015-05-29 15:53:22 +02002635 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002636 goto end;
2637
Remi Gacogne47783ef2015-05-29 15:53:22 +02002638 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2639
2640end:
2641 if (in)
2642 BIO_free(in);
2643
Emeric Brune1b4ed42018-08-16 15:14:12 +02002644 ERR_clear_error();
2645
Remi Gacogne47783ef2015-05-29 15:53:22 +02002646 return dh;
2647}
2648
2649int ssl_sock_load_global_dh_param_from_file(const char *filename)
2650{
2651 global_dh = ssl_sock_get_dh_from_file(filename);
2652
2653 if (global_dh) {
2654 return 0;
2655 }
2656
2657 return -1;
2658}
2659
2660/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002661 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002662int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2663{
2664 int ret = -1;
2665 DH *dh = ssl_sock_get_dh_from_file(file);
2666
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002667 if (dh) {
2668 ret = 1;
2669 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002670
2671 if (ssl_dh_ptr_index >= 0) {
2672 /* store a pointer to the DH params to avoid complaining about
2673 ssl-default-dh-param not being set for this SSL_CTX */
2674 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2675 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002676 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002677 else if (global_dh) {
2678 SSL_CTX_set_tmp_dh(ctx, global_dh);
2679 ret = 0; /* DH params not found */
2680 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002681 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002682 /* Clear openssl global errors stack */
2683 ERR_clear_error();
2684
Willy Tarreauef934602016-12-22 23:12:01 +01002685 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002686 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002687 if (local_dh_1024 == NULL)
2688 local_dh_1024 = ssl_get_dh_1024();
2689
Remi Gacogne8de54152014-07-15 11:36:40 +02002690 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002691 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002692
Remi Gacogne8de54152014-07-15 11:36:40 +02002693 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002694 }
2695 else {
2696 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2697 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002698
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002699 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002700 }
Emeric Brun644cde02012-12-14 11:21:13 +01002701
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002702end:
2703 if (dh)
2704 DH_free(dh);
2705
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002706 return ret;
2707}
2708#endif
2709
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002710static 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 +02002711 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002712{
2713 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002714 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002715 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002716
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002717 if (*name == '!') {
2718 neg = 1;
2719 name++;
2720 }
2721 if (*name == '*') {
2722 wild = 1;
2723 name++;
2724 }
2725 /* !* filter is a nop */
2726 if (neg && wild)
2727 return order;
2728 if (*name) {
2729 int j, len;
2730 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002731 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002732 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002733 if (j >= trash.size)
2734 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002735 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002736
2737 /* Check for duplicates. */
2738 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002739 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002740 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002741 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002742 for (; node; node = ebmb_next_dup(node)) {
2743 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002744 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002745 return order;
2746 }
2747
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002748 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002749 if (!sc)
2750 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002751 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002752 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002753 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002754 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002755 sc->order = order++;
2756 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002757 if (kinfo.sig != TLSEXT_signature_anonymous)
2758 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002759 if (wild)
2760 ebst_insert(&s->sni_w_ctx, &sc->name);
2761 else
2762 ebst_insert(&s->sni_ctx, &sc->name);
2763 }
2764 return order;
2765}
2766
yanbzhu488a4d22015-12-01 15:16:07 -05002767
2768/* The following code is used for loading multiple crt files into
2769 * SSL_CTX's based on CN/SAN
2770 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002771#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002772/* This is used to preload the certifcate, private key
2773 * and Cert Chain of a file passed in via the crt
2774 * argument
2775 *
2776 * This way, we do not have to read the file multiple times
2777 */
2778struct cert_key_and_chain {
2779 X509 *cert;
2780 EVP_PKEY *key;
2781 unsigned int num_chain_certs;
2782 /* This is an array of X509 pointers */
2783 X509 **chain_certs;
2784};
2785
yanbzhu08ce6ab2015-12-02 13:01:29 -05002786#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2787
2788struct key_combo_ctx {
2789 SSL_CTX *ctx;
2790 int order;
2791};
2792
2793/* Map used for processing multiple keypairs for a single purpose
2794 *
2795 * This maps CN/SNI name to certificate type
2796 */
2797struct sni_keytype {
2798 int keytypes; /* BITMASK for keytypes */
2799 struct ebmb_node name; /* node holding the servername value */
2800};
2801
2802
yanbzhu488a4d22015-12-01 15:16:07 -05002803/* Frees the contents of a cert_key_and_chain
2804 */
2805static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2806{
2807 int i;
2808
2809 if (!ckch)
2810 return;
2811
2812 /* Free the certificate and set pointer to NULL */
2813 if (ckch->cert)
2814 X509_free(ckch->cert);
2815 ckch->cert = NULL;
2816
2817 /* Free the key and set pointer to NULL */
2818 if (ckch->key)
2819 EVP_PKEY_free(ckch->key);
2820 ckch->key = NULL;
2821
2822 /* Free each certificate in the chain */
2823 for (i = 0; i < ckch->num_chain_certs; i++) {
2824 if (ckch->chain_certs[i])
2825 X509_free(ckch->chain_certs[i]);
2826 }
2827
2828 /* Free the chain obj itself and set to NULL */
2829 if (ckch->num_chain_certs > 0) {
2830 free(ckch->chain_certs);
2831 ckch->num_chain_certs = 0;
2832 ckch->chain_certs = NULL;
2833 }
2834
2835}
2836
2837/* checks if a key and cert exists in the ckch
2838 */
2839static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2840{
2841 return (ckch->cert != NULL && ckch->key != NULL);
2842}
2843
2844
2845/* Loads the contents of a crt file (path) into a cert_key_and_chain
2846 * This allows us to carry the contents of the file without having to
2847 * read the file multiple times.
2848 *
2849 * returns:
2850 * 0 on Success
2851 * 1 on SSL Failure
2852 * 2 on file not found
2853 */
2854static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2855{
2856
2857 BIO *in;
2858 X509 *ca = NULL;
2859 int ret = 1;
2860
2861 ssl_sock_free_cert_key_and_chain_contents(ckch);
2862
2863 in = BIO_new(BIO_s_file());
2864 if (in == NULL)
2865 goto end;
2866
2867 if (BIO_read_filename(in, path) <= 0)
2868 goto end;
2869
yanbzhu488a4d22015-12-01 15:16:07 -05002870 /* Read Private Key */
2871 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2872 if (ckch->key == NULL) {
2873 memprintf(err, "%sunable to load private key from file '%s'.\n",
2874 err && *err ? *err : "", path);
2875 goto end;
2876 }
2877
Willy Tarreaubb137a82016-04-06 19:02:38 +02002878 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002879 if (BIO_reset(in) == -1) {
2880 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2881 err && *err ? *err : "", path);
2882 goto end;
2883 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002884
2885 /* Read Certificate */
2886 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2887 if (ckch->cert == NULL) {
2888 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2889 err && *err ? *err : "", path);
2890 goto end;
2891 }
2892
yanbzhu488a4d22015-12-01 15:16:07 -05002893 /* Read Certificate Chain */
2894 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2895 /* Grow the chain certs */
2896 ckch->num_chain_certs++;
2897 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2898
2899 /* use - 1 here since we just incremented it above */
2900 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2901 }
2902 ret = ERR_get_error();
2903 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2904 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2905 err && *err ? *err : "", path);
2906 ret = 1;
2907 goto end;
2908 }
2909
2910 ret = 0;
2911
2912end:
2913
2914 ERR_clear_error();
2915 if (in)
2916 BIO_free(in);
2917
2918 /* Something went wrong in one of the reads */
2919 if (ret != 0)
2920 ssl_sock_free_cert_key_and_chain_contents(ckch);
2921
2922 return ret;
2923}
2924
2925/* Loads the info in ckch into ctx
2926 * Currently, this does not process any information about ocsp, dhparams or
2927 * sctl
2928 * Returns
2929 * 0 on success
2930 * 1 on failure
2931 */
2932static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2933{
2934 int i = 0;
2935
2936 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2937 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2938 err && *err ? *err : "", path);
2939 return 1;
2940 }
2941
2942 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2943 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2944 err && *err ? *err : "", path);
2945 return 1;
2946 }
2947
yanbzhu488a4d22015-12-01 15:16:07 -05002948 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2949 for (i = 0; i < ckch->num_chain_certs; i++) {
2950 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002951 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2952 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002953 return 1;
2954 }
2955 }
2956
2957 if (SSL_CTX_check_private_key(ctx) <= 0) {
2958 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2959 err && *err ? *err : "", path);
2960 return 1;
2961 }
2962
2963 return 0;
2964}
2965
yanbzhu08ce6ab2015-12-02 13:01:29 -05002966
2967static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2968{
2969 struct sni_keytype *s_kt = NULL;
2970 struct ebmb_node *node;
2971 int i;
2972
2973 for (i = 0; i < trash.size; i++) {
2974 if (!str[i])
2975 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002976 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002977 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002978 trash.area[i] = 0;
2979 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002980 if (!node) {
2981 /* CN not found in tree */
2982 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2983 /* Using memcpy here instead of strncpy.
2984 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2985 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2986 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002987 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002988 s_kt->keytypes = 0;
2989 ebst_insert(sni_keytypes, &s_kt->name);
2990 } else {
2991 /* CN found in tree */
2992 s_kt = container_of(node, struct sni_keytype, name);
2993 }
2994
2995 /* Mark that this CN has the keytype of key_index via keytypes mask */
2996 s_kt->keytypes |= 1<<key_index;
2997
2998}
2999
3000
3001/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3002 * If any are found, group these files into a set of SSL_CTX*
3003 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3004 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003005 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003006 *
3007 * Returns
3008 * 0 on success
3009 * 1 on failure
3010 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003011static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3012 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003013{
3014 char fp[MAXPATHLEN+1] = {0};
3015 int n = 0;
3016 int i = 0;
3017 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3018 struct eb_root sni_keytypes_map = { {0} };
3019 struct ebmb_node *node;
3020 struct ebmb_node *next;
3021 /* Array of SSL_CTX pointers corresponding to each possible combo
3022 * of keytypes
3023 */
3024 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3025 int rv = 0;
3026 X509_NAME *xname = NULL;
3027 char *str = NULL;
3028#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3029 STACK_OF(GENERAL_NAME) *names = NULL;
3030#endif
3031
3032 /* Load all possible certs and keys */
3033 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3034 struct stat buf;
3035
3036 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3037 if (stat(fp, &buf) == 0) {
3038 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3039 rv = 1;
3040 goto end;
3041 }
3042 }
3043 }
3044
3045 /* Process each ckch and update keytypes for each CN/SAN
3046 * for example, if CN/SAN www.a.com is associated with
3047 * certs with keytype 0 and 2, then at the end of the loop,
3048 * www.a.com will have:
3049 * keyindex = 0 | 1 | 4 = 5
3050 */
3051 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3052
3053 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3054 continue;
3055
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003056 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003057 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003058 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3059 } else {
3060 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3061 * so the line that contains logic is marked via comments
3062 */
3063 xname = X509_get_subject_name(certs_and_keys[n].cert);
3064 i = -1;
3065 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3066 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003067 ASN1_STRING *value;
3068 value = X509_NAME_ENTRY_get_data(entry);
3069 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003070 /* Important line is here */
3071 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003072
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003073 OPENSSL_free(str);
3074 str = NULL;
3075 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003076 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003078 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003079#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003080 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3081 if (names) {
3082 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3083 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003085 if (name->type == GEN_DNS) {
3086 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3087 /* Important line is here */
3088 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003089
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003090 OPENSSL_free(str);
3091 str = NULL;
3092 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003093 }
3094 }
3095 }
3096 }
3097#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3098 }
3099
3100 /* If no files found, return error */
3101 if (eb_is_empty(&sni_keytypes_map)) {
3102 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3103 err && *err ? *err : "", path);
3104 rv = 1;
3105 goto end;
3106 }
3107
3108 /* We now have a map of CN/SAN to keytypes that are loaded in
3109 * Iterate through the map to create the SSL_CTX's (if needed)
3110 * and add each CTX to the SNI tree
3111 *
3112 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003113 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003114 * combination is denoted by the key in the map. Each key
3115 * has a value between 1 and 2^n - 1. Conveniently, the array
3116 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3117 * entry in the array to correspond to the unique combo (key)
3118 * associated with i. This unique key combo (i) will be associated
3119 * with combos[i-1]
3120 */
3121
3122 node = ebmb_first(&sni_keytypes_map);
3123 while (node) {
3124 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003125 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003126 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003127
3128 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3129 i = container_of(node, struct sni_keytype, name)->keytypes;
3130 cur_ctx = key_combos[i-1].ctx;
3131
3132 if (cur_ctx == NULL) {
3133 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003134 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003135 if (cur_ctx == NULL) {
3136 memprintf(err, "%sunable to allocate SSL context.\n",
3137 err && *err ? *err : "");
3138 rv = 1;
3139 goto end;
3140 }
3141
yanbzhube2774d2015-12-10 15:07:30 -05003142 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003143 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3144 if (i & (1<<n)) {
3145 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003146 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3147 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003148 SSL_CTX_free(cur_ctx);
3149 rv = 1;
3150 goto end;
3151 }
yanbzhube2774d2015-12-10 15:07:30 -05003152
3153#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3154 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003155 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003156 if (err)
3157 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 +00003158 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003159 SSL_CTX_free(cur_ctx);
3160 rv = 1;
3161 goto end;
3162 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003163#elif (defined OPENSSL_IS_BORINGSSL)
3164 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003165#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003166 }
3167 }
3168
3169 /* Load DH params into the ctx to support DHE keys */
3170#ifndef OPENSSL_NO_DH
3171 if (ssl_dh_ptr_index >= 0)
3172 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3173
3174 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3175 if (rv < 0) {
3176 if (err)
3177 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3178 *err ? *err : "", path);
3179 rv = 1;
3180 goto end;
3181 }
3182#endif
3183
3184 /* Update key_combos */
3185 key_combos[i-1].ctx = cur_ctx;
3186 }
3187
3188 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003189 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003190 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003191 node = ebmb_next(node);
3192 }
3193
3194
3195 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3196 if (!bind_conf->default_ctx) {
3197 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3198 if (key_combos[i].ctx) {
3199 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003200 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003201 break;
3202 }
3203 }
3204 }
3205
3206end:
3207
3208 if (names)
3209 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3210
3211 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3212 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3213
3214 node = ebmb_first(&sni_keytypes_map);
3215 while (node) {
3216 next = ebmb_next(node);
3217 ebmb_delete(node);
3218 node = next;
3219 }
3220
3221 return rv;
3222}
3223#else
3224/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003225static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3226 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003227{
3228 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3229 err && *err ? *err : "", path, strerror(errno));
3230 return 1;
3231}
3232
yanbzhu488a4d22015-12-01 15:16:07 -05003233#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3234
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3236 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3237 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003238static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3239 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003240{
3241 BIO *in;
3242 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003243 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003244 int ret = -1;
3245 int order = 0;
3246 X509_NAME *xname;
3247 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003248 pem_password_cb *passwd_cb;
3249 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003250 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003251 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003252
Emeric Brunfc0421f2012-09-07 17:30:07 +02003253#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3254 STACK_OF(GENERAL_NAME) *names;
3255#endif
3256
3257 in = BIO_new(BIO_s_file());
3258 if (in == NULL)
3259 goto end;
3260
3261 if (BIO_read_filename(in, file) <= 0)
3262 goto end;
3263
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264
3265 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3266 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3267
3268 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003269 if (x == NULL)
3270 goto end;
3271
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003272 pkey = X509_get_pubkey(x);
3273 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003274 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003275 switch(EVP_PKEY_base_id(pkey)) {
3276 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003277 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003278 break;
3279 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003280 kinfo.sig = TLSEXT_signature_ecdsa;
3281 break;
3282 case EVP_PKEY_DSA:
3283 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003284 break;
3285 }
3286 EVP_PKEY_free(pkey);
3287 }
3288
Emeric Brun50bcecc2013-04-22 13:05:23 +02003289 if (fcount) {
3290 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003291 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003292 }
3293 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003295 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3296 if (names) {
3297 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3298 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3299 if (name->type == GEN_DNS) {
3300 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003301 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003302 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003303 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003304 }
3305 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003306 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003307 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003308#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003309 xname = X509_get_subject_name(x);
3310 i = -1;
3311 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3312 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003313 ASN1_STRING *value;
3314
3315 value = X509_NAME_ENTRY_get_data(entry);
3316 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003317 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003318 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003319 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003320 }
3321 }
3322
3323 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3324 if (!SSL_CTX_use_certificate(ctx, x))
3325 goto end;
3326
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003327#ifdef SSL_CTX_clear_extra_chain_certs
3328 SSL_CTX_clear_extra_chain_certs(ctx);
3329#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003330 if (ctx->extra_certs != NULL) {
3331 sk_X509_pop_free(ctx->extra_certs, X509_free);
3332 ctx->extra_certs = NULL;
3333 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003334#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003335
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003336 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003337 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3338 X509_free(ca);
3339 goto end;
3340 }
3341 }
3342
3343 err = ERR_get_error();
3344 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3345 /* we successfully reached the last cert in the file */
3346 ret = 1;
3347 }
3348 ERR_clear_error();
3349
3350end:
3351 if (x)
3352 X509_free(x);
3353
3354 if (in)
3355 BIO_free(in);
3356
3357 return ret;
3358}
3359
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003360static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3361 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003362{
3363 int ret;
3364 SSL_CTX *ctx;
3365
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003366 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003368 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3369 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003370 return 1;
3371 }
3372
3373 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003374 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3375 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003376 SSL_CTX_free(ctx);
3377 return 1;
3378 }
3379
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003380 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003381 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003382 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3383 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003384 if (ret < 0) /* serious error, must do that ourselves */
3385 SSL_CTX_free(ctx);
3386 return 1;
3387 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003388
3389 if (SSL_CTX_check_private_key(ctx) <= 0) {
3390 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3391 err && *err ? *err : "", path);
3392 return 1;
3393 }
3394
Emeric Brunfc0421f2012-09-07 17:30:07 +02003395 /* we must not free the SSL_CTX anymore below, since it's already in
3396 * the tree, so it will be discovered and cleaned in time.
3397 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003398#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003399 /* store a NULL pointer to indicate we have not yet loaded
3400 a custom DH param file */
3401 if (ssl_dh_ptr_index >= 0) {
3402 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3403 }
3404
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003405 ret = ssl_sock_load_dh_params(ctx, path);
3406 if (ret < 0) {
3407 if (err)
3408 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3409 *err ? *err : "", path);
3410 return 1;
3411 }
3412#endif
3413
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003414#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003415 ret = ssl_sock_load_ocsp(ctx, path);
3416 if (ret < 0) {
3417 if (err)
3418 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",
3419 *err ? *err : "", path);
3420 return 1;
3421 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003422#elif (defined OPENSSL_IS_BORINGSSL)
3423 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003424#endif
3425
Daniel Jakots54ffb912015-11-06 20:02:41 +01003426#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003427 if (sctl_ex_index >= 0) {
3428 ret = ssl_sock_load_sctl(ctx, path);
3429 if (ret < 0) {
3430 if (err)
3431 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3432 *err ? *err : "", path);
3433 return 1;
3434 }
3435 }
3436#endif
3437
Emeric Brunfc0421f2012-09-07 17:30:07 +02003438#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003439 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003440 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3441 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003442 return 1;
3443 }
3444#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003445 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003446 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003447 bind_conf->default_ssl_conf = ssl_conf;
3448 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003449
3450 return 0;
3451}
3452
Willy Tarreau03209342016-12-22 17:08:28 +01003453int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003454{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003455 struct dirent **de_list;
3456 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003457 DIR *dir;
3458 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003459 char *end;
3460 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003461 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003462#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3463 int is_bundle;
3464 int j;
3465#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467 if (stat(path, &buf) == 0) {
3468 dir = opendir(path);
3469 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003470 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003471
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 /* strip trailing slashes, including first one */
3473 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3474 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003475
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476 n = scandir(path, &de_list, 0, alphasort);
3477 if (n < 0) {
3478 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3479 err && *err ? *err : "", path, strerror(errno));
3480 cfgerr++;
3481 }
3482 else {
3483 for (i = 0; i < n; i++) {
3484 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003485
yanbzhu08ce6ab2015-12-02 13:01:29 -05003486 end = strrchr(de->d_name, '.');
3487 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3488 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003489
yanbzhu08ce6ab2015-12-02 13:01:29 -05003490 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3491 if (stat(fp, &buf) != 0) {
3492 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3493 err && *err ? *err : "", fp, strerror(errno));
3494 cfgerr++;
3495 goto ignore_entry;
3496 }
3497 if (!S_ISREG(buf.st_mode))
3498 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003499
3500#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3501 is_bundle = 0;
3502 /* Check if current entry in directory is part of a multi-cert bundle */
3503
3504 if (end) {
3505 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3506 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3507 is_bundle = 1;
3508 break;
3509 }
3510 }
3511
3512 if (is_bundle) {
3513 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3514 int dp_len;
3515
3516 dp_len = end - de->d_name;
3517 snprintf(dp, dp_len + 1, "%s", de->d_name);
3518
3519 /* increment i and free de until we get to a non-bundle cert
3520 * Note here that we look at de_list[i + 1] before freeing de
3521 * this is important since ignore_entry will free de
3522 */
3523 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3524 free(de);
3525 i++;
3526 de = de_list[i];
3527 }
3528
3529 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003530 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003531
3532 /* Successfully processed the bundle */
3533 goto ignore_entry;
3534 }
3535 }
3536
3537#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003539ignore_entry:
3540 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003541 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003542 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003543 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003544 closedir(dir);
3545 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003546 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003547
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003548 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003549
Emeric Brunfc0421f2012-09-07 17:30:07 +02003550 return cfgerr;
3551}
3552
Thierry Fournier383085f2013-01-24 14:15:43 +01003553/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3554 * done once. Zero is returned if the operation fails. No error is returned
3555 * if the random is said as not implemented, because we expect that openssl
3556 * will use another method once needed.
3557 */
3558static int ssl_initialize_random()
3559{
3560 unsigned char random;
3561 static int random_initialized = 0;
3562
3563 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3564 random_initialized = 1;
3565
3566 return random_initialized;
3567}
3568
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003569/* release ssl bind conf */
3570void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003571{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003572 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003573#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003574 free(conf->npn_str);
3575 conf->npn_str = NULL;
3576#endif
3577#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3578 free(conf->alpn_str);
3579 conf->alpn_str = NULL;
3580#endif
3581 free(conf->ca_file);
3582 conf->ca_file = NULL;
3583 free(conf->crl_file);
3584 conf->crl_file = NULL;
3585 free(conf->ciphers);
3586 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003587#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3588 free(conf->ciphersuites);
3589 conf->ciphersuites = NULL;
3590#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003591 free(conf->curves);
3592 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003593 free(conf->ecdhe);
3594 conf->ecdhe = NULL;
3595 }
3596}
3597
3598int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3599{
3600 char thisline[CRT_LINESIZE];
3601 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003602 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003603 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 int linenum = 0;
3605 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606
Willy Tarreauad1731d2013-04-02 17:35:58 +02003607 if ((f = fopen(file, "r")) == NULL) {
3608 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003609 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003610 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611
3612 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003613 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003616 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003617 char *crt_path;
3618 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003619
3620 linenum++;
3621 end = line + strlen(line);
3622 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3623 /* Check if we reached the limit and the last char is not \n.
3624 * Watch out for the last line without the terminating '\n'!
3625 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003626 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3627 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003628 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003629 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003630 }
3631
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003632 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003633 newarg = 1;
3634 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003635 if (*line == '#' || *line == '\n' || *line == '\r') {
3636 /* end of string, end of loop */
3637 *line = 0;
3638 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003639 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003640 newarg = 1;
3641 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003642 } else if (*line == '[') {
3643 if (ssl_b) {
3644 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3645 cfgerr = 1;
3646 break;
3647 }
3648 if (!arg) {
3649 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3650 cfgerr = 1;
3651 break;
3652 }
3653 ssl_b = arg;
3654 newarg = 1;
3655 *line = 0;
3656 } else if (*line == ']') {
3657 if (ssl_e) {
3658 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003659 cfgerr = 1;
3660 break;
3661 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003662 if (!ssl_b) {
3663 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3664 cfgerr = 1;
3665 break;
3666 }
3667 ssl_e = arg;
3668 newarg = 1;
3669 *line = 0;
3670 } else if (newarg) {
3671 if (arg == MAX_CRT_ARGS) {
3672 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3673 cfgerr = 1;
3674 break;
3675 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003676 newarg = 0;
3677 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003678 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003679 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003680 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003681 if (cfgerr)
3682 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003683 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003684
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003685 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003686 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003687 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003688
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003689 crt_path = args[0];
3690 if (*crt_path != '/' && global_ssl.crt_base) {
3691 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3692 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3693 crt_path, linenum, file);
3694 cfgerr = 1;
3695 break;
3696 }
3697 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3698 crt_path = path;
3699 }
3700
3701 ssl_conf = calloc(1, sizeof *ssl_conf);
3702 cur_arg = ssl_b ? ssl_b : 1;
3703 while (cur_arg < ssl_e) {
3704 newarg = 0;
3705 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3706 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3707 newarg = 1;
3708 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3709 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3710 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3711 args[cur_arg], linenum, file);
3712 cfgerr = 1;
3713 }
3714 cur_arg += 1 + ssl_bind_kws[i].skip;
3715 break;
3716 }
3717 }
3718 if (!cfgerr && !newarg) {
3719 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3720 args[cur_arg], linenum, file);
3721 cfgerr = 1;
3722 break;
3723 }
3724 }
3725 if (cfgerr) {
3726 ssl_sock_free_ssl_conf(ssl_conf);
3727 free(ssl_conf);
3728 ssl_conf = NULL;
3729 break;
3730 }
3731
3732 if (stat(crt_path, &buf) == 0) {
3733 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3734 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003735 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003736 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3737 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003738 }
3739
Willy Tarreauad1731d2013-04-02 17:35:58 +02003740 if (cfgerr) {
3741 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003742 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003743 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003744 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003745 fclose(f);
3746 return cfgerr;
3747}
3748
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003749/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003750static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003751ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003752{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003753 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003754 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003755 SSL_OP_ALL | /* all known workarounds for bugs */
3756 SSL_OP_NO_SSLv2 |
3757 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003758 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003759 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003760 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003761 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003762 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003763 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003764 SSL_MODE_ENABLE_PARTIAL_WRITE |
3765 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003766 SSL_MODE_RELEASE_BUFFERS |
3767 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003768 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003769 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003770 int flags = MC_SSL_O_ALL;
3771 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003772
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003773 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003774 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003776 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003777 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3778 "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);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003780 else
3781 flags = conf_ssl_methods->flags;
3782
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003783 min = conf_ssl_methods->min;
3784 max = conf_ssl_methods->max;
3785 /* start with TLSv10 to remove SSLv3 per default */
3786 if (!min && (!max || max >= CONF_TLSV10))
3787 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003788 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003789 if (min)
3790 flags |= (methodVersions[min].flag - 1);
3791 if (max)
3792 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003793 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003794 min = max = CONF_TLSV_NONE;
3795 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003796 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003797 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003798 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003799 if (min) {
3800 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003801 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3802 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3803 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3804 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003805 hole = 0;
3806 }
3807 max = i;
3808 }
3809 else {
3810 min = max = i;
3811 }
3812 }
3813 else {
3814 if (min)
3815 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003816 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003817 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003818 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3819 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003820 cfgerr += 1;
3821 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003822 /* save real min/max in bind_conf */
3823 conf_ssl_methods->min = min;
3824 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003825
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003826#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003827 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003828 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003829 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003830 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003831 else
3832 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3833 if (flags & methodVersions[i].flag)
3834 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003835#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003836 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003837 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3838 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003839#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003840
3841 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3842 options |= SSL_OP_NO_TICKET;
3843 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3844 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3845 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003846
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003847#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003848 if (global_ssl.async)
3849 mode |= SSL_MODE_ASYNC;
3850#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003851 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003852 if (global_ssl.life_time)
3853 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003854
3855#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3856#ifdef OPENSSL_IS_BORINGSSL
3857 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3858 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003859#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3860 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3861 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003862#else
3863 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003864#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003865 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003866#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003867 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003868}
3869
William Lallemand4f45bb92017-10-30 20:08:51 +01003870
3871static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3872{
3873 if (first == block) {
3874 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3875 if (first->len > 0)
3876 sh_ssl_sess_tree_delete(sh_ssl_sess);
3877 }
3878}
3879
3880/* return first block from sh_ssl_sess */
3881static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3882{
3883 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3884
3885}
3886
3887/* store a session into the cache
3888 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3889 * data: asn1 encoded session
3890 * data_len: asn1 encoded session length
3891 * Returns 1 id session was stored (else 0)
3892 */
3893static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3894{
3895 struct shared_block *first;
3896 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3897
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003898 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003899 if (!first) {
3900 /* Could not retrieve enough free blocks to store that session */
3901 return 0;
3902 }
3903
3904 /* STORE the key in the first elem */
3905 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3906 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3907 first->len = sizeof(struct sh_ssl_sess_hdr);
3908
3909 /* it returns the already existing node
3910 or current node if none, never returns null */
3911 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3912 if (oldsh_ssl_sess != sh_ssl_sess) {
3913 /* NOTE: Row couldn't be in use because we lock read & write function */
3914 /* release the reserved row */
3915 shctx_row_dec_hot(ssl_shctx, first);
3916 /* replace the previous session already in the tree */
3917 sh_ssl_sess = oldsh_ssl_sess;
3918 /* ignore the previous session data, only use the header */
3919 first = sh_ssl_sess_first_block(sh_ssl_sess);
3920 shctx_row_inc_hot(ssl_shctx, first);
3921 first->len = sizeof(struct sh_ssl_sess_hdr);
3922 }
3923
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003924 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003925 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003926 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003927 }
3928
3929 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003930
3931 return 1;
3932}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003933
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003934/* SSL callback used when a new session is created while connecting to a server */
3935static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3936{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003937 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003938 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003939
Willy Tarreau07d94e42018-09-20 10:57:52 +02003940 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003941
Olivier Houcharde6060c52017-11-16 17:42:52 +01003942 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3943 int len;
3944 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003945
Olivier Houcharde6060c52017-11-16 17:42:52 +01003946 len = i2d_SSL_SESSION(sess, NULL);
3947 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3948 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3949 } else {
3950 free(s->ssl_ctx.reused_sess[tid].ptr);
3951 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3952 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3953 }
3954 if (s->ssl_ctx.reused_sess[tid].ptr) {
3955 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3956 &ptr);
3957 }
3958 } else {
3959 free(s->ssl_ctx.reused_sess[tid].ptr);
3960 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3961 }
3962
3963 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003964}
3965
Olivier Houcharde6060c52017-11-16 17:42:52 +01003966
William Lallemanded0b5ad2017-10-30 19:36:36 +01003967/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003968int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003969{
3970 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3971 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3972 unsigned char *p;
3973 int data_len;
3974 unsigned int sid_length, sid_ctx_length;
3975 const unsigned char *sid_data;
3976 const unsigned char *sid_ctx_data;
3977
3978 /* Session id is already stored in to key and session id is known
3979 * so we dont store it to keep size.
3980 */
3981
3982 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3983 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3984 SSL_SESSION_set1_id(sess, sid_data, 0);
3985 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3986
3987 /* check if buffer is large enough for the ASN1 encoded session */
3988 data_len = i2d_SSL_SESSION(sess, NULL);
3989 if (data_len > SHSESS_MAX_DATA_LEN)
3990 goto err;
3991
3992 p = encsess;
3993
3994 /* process ASN1 session encoding before the lock */
3995 i2d_SSL_SESSION(sess, &p);
3996
3997 memcpy(encid, sid_data, sid_length);
3998 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3999 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4000
William Lallemanda3c77cf2017-10-30 23:44:40 +01004001 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004002 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004003 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004004 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004005err:
4006 /* reset original length values */
4007 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4008 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4009
4010 return 0; /* do not increment session reference count */
4011}
4012
4013/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004014SSL_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 +01004015{
William Lallemand4f45bb92017-10-30 20:08:51 +01004016 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004017 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4018 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004019 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004020 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004021
4022 global.shctx_lookups++;
4023
4024 /* allow the session to be freed automatically by openssl */
4025 *do_copy = 0;
4026
4027 /* tree key is zeros padded sessionid */
4028 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4029 memcpy(tmpkey, key, key_len);
4030 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4031 key = tmpkey;
4032 }
4033
4034 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004035 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004036
4037 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004038 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4039 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004040 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004041 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004042 global.shctx_misses++;
4043 return NULL;
4044 }
4045
William Lallemand4f45bb92017-10-30 20:08:51 +01004046 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4047 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004048
William Lallemand4f45bb92017-10-30 20:08:51 +01004049 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 +01004050
William Lallemanda3c77cf2017-10-30 23:44:40 +01004051 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004052
4053 /* decode ASN1 session */
4054 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004055 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056 /* Reset session id and session id contenxt */
4057 if (sess) {
4058 SSL_SESSION_set1_id(sess, key, key_len);
4059 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4060 }
4061
4062 return sess;
4063}
4064
William Lallemand4f45bb92017-10-30 20:08:51 +01004065
William Lallemanded0b5ad2017-10-30 19:36:36 +01004066/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004067void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004068{
William Lallemand4f45bb92017-10-30 20:08:51 +01004069 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004070 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4071 unsigned int sid_length;
4072 const unsigned char *sid_data;
4073 (void)ctx;
4074
4075 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4076 /* tree key is zeros padded sessionid */
4077 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4078 memcpy(tmpkey, sid_data, sid_length);
4079 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4080 sid_data = tmpkey;
4081 }
4082
William Lallemanda3c77cf2017-10-30 23:44:40 +01004083 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004084
4085 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004086 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4087 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004088 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004089 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004090 }
4091
4092 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004093 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004094}
4095
4096/* Set session cache mode to server and disable openssl internal cache.
4097 * Set shared cache callbacks on an ssl context.
4098 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004099void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004100{
4101 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4102
4103 if (!ssl_shctx) {
4104 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4105 return;
4106 }
4107
4108 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4109 SSL_SESS_CACHE_NO_INTERNAL |
4110 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4111
4112 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004113 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4114 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4115 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004116}
4117
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004118int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4119{
4120 struct proxy *curproxy = bind_conf->frontend;
4121 int cfgerr = 0;
4122 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004123 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004124 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004125#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4126 const char *conf_ciphersuites;
4127#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004128 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004129
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004130 if (ssl_conf) {
4131 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4132 int i, min, max;
4133 int flags = MC_SSL_O_ALL;
4134
4135 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004136 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4137 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004138 if (min)
4139 flags |= (methodVersions[min].flag - 1);
4140 if (max)
4141 flags |= ~((methodVersions[max].flag << 1) - 1);
4142 min = max = CONF_TLSV_NONE;
4143 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4144 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4145 if (min)
4146 max = i;
4147 else
4148 min = max = i;
4149 }
4150 /* save real min/max */
4151 conf_ssl_methods->min = min;
4152 conf_ssl_methods->max = max;
4153 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004154 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4155 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004156 cfgerr += 1;
4157 }
4158 }
4159
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004160 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004161 case SSL_SOCK_VERIFY_NONE:
4162 verify = SSL_VERIFY_NONE;
4163 break;
4164 case SSL_SOCK_VERIFY_OPTIONAL:
4165 verify = SSL_VERIFY_PEER;
4166 break;
4167 case SSL_SOCK_VERIFY_REQUIRED:
4168 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4169 break;
4170 }
4171 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4172 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004173 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4174 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4175 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004176 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004177 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004178 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4179 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004180 cfgerr++;
4181 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004182 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4183 /* set CA names for client cert request, function returns void */
4184 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4185 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004186 }
Emeric Brun850efd52014-01-29 12:24:34 +01004187 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004188 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4189 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004190 cfgerr++;
4191 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004192#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004193 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004194 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4195
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004196 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004197 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4198 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004199 cfgerr++;
4200 }
Emeric Brun561e5742012-10-02 15:20:55 +02004201 else {
4202 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4203 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004204 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004205#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004206 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004207 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004208#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004209 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004210 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004211 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4212 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004213 cfgerr++;
4214 }
4215 }
4216#endif
4217
William Lallemand4f45bb92017-10-30 20:08:51 +01004218 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004219 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4220 if (conf_ciphers &&
4221 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004222 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4223 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004224 cfgerr++;
4225 }
4226
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004227#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4228 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4229 if (conf_ciphersuites &&
4230 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4231 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4232 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4233 cfgerr++;
4234 }
4235#endif
4236
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004237#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004238 /* If tune.ssl.default-dh-param has not been set,
4239 neither has ssl-default-dh-file and no static DH
4240 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004241 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004242 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004243 (ssl_dh_ptr_index == -1 ||
4244 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004245 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4246 const SSL_CIPHER * cipher = NULL;
4247 char cipher_description[128];
4248 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4249 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4250 which is not ephemeral DH. */
4251 const char dhe_description[] = " Kx=DH ";
4252 const char dhe_export_description[] = " Kx=DH(";
4253 int idx = 0;
4254 int dhe_found = 0;
4255 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004256
Remi Gacogne23d5d372014-10-10 17:04:26 +02004257 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004258
Remi Gacogne23d5d372014-10-10 17:04:26 +02004259 if (ssl) {
4260 ciphers = SSL_get_ciphers(ssl);
4261
4262 if (ciphers) {
4263 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4264 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4265 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4266 if (strstr(cipher_description, dhe_description) != NULL ||
4267 strstr(cipher_description, dhe_export_description) != NULL) {
4268 dhe_found = 1;
4269 break;
4270 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004271 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004272 }
4273 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004274 SSL_free(ssl);
4275 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004276 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004277
Lukas Tribus90132722014-08-18 00:56:33 +02004278 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004279 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 +02004280 }
4281
Willy Tarreauef934602016-12-22 23:12:01 +01004282 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004283 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004284
Willy Tarreauef934602016-12-22 23:12:01 +01004285 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004286 if (local_dh_1024 == NULL) {
4287 local_dh_1024 = ssl_get_dh_1024();
4288 }
Willy Tarreauef934602016-12-22 23:12:01 +01004289 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004290 if (local_dh_2048 == NULL) {
4291 local_dh_2048 = ssl_get_dh_2048();
4292 }
Willy Tarreauef934602016-12-22 23:12:01 +01004293 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004294 if (local_dh_4096 == NULL) {
4295 local_dh_4096 = ssl_get_dh_4096();
4296 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004297 }
4298 }
4299 }
4300#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004301
Emeric Brunfc0421f2012-09-07 17:30:07 +02004302 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004303#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004304 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004305#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004306
Bernard Spil13c53f82018-02-15 13:34:58 +01004307#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004308 ssl_conf_cur = NULL;
4309 if (ssl_conf && ssl_conf->npn_str)
4310 ssl_conf_cur = ssl_conf;
4311 else if (bind_conf->ssl_conf.npn_str)
4312 ssl_conf_cur = &bind_conf->ssl_conf;
4313 if (ssl_conf_cur)
4314 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004315#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004316#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004317 ssl_conf_cur = NULL;
4318 if (ssl_conf && ssl_conf->alpn_str)
4319 ssl_conf_cur = ssl_conf;
4320 else if (bind_conf->ssl_conf.alpn_str)
4321 ssl_conf_cur = &bind_conf->ssl_conf;
4322 if (ssl_conf_cur)
4323 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004324#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004325#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4326 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4327 if (conf_curves) {
4328 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004329 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4330 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004331 cfgerr++;
4332 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004333#if defined(SSL_CTX_set_ecdh_auto)
4334 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4335#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004336 }
4337#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004338#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004339 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004340 int i;
4341 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004342#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004343 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004344 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4345 NULL);
4346
4347 if (ecdhe == NULL) {
4348 SSL_CTX_set_dh_auto(ctx, 1);
4349 return cfgerr;
4350 }
4351#else
4352 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4353 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4354 ECDHE_DEFAULT_CURVE);
4355#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004356
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004357 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004358 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004359 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4360 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004361 cfgerr++;
4362 }
4363 else {
4364 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4365 EC_KEY_free(ecdh);
4366 }
4367 }
4368#endif
4369
Emeric Brunfc0421f2012-09-07 17:30:07 +02004370 return cfgerr;
4371}
4372
Evan Broderbe554312013-06-27 00:05:25 -07004373static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4374{
4375 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4376 size_t prefixlen, suffixlen;
4377
4378 /* Trivial case */
4379 if (strcmp(pattern, hostname) == 0)
4380 return 1;
4381
Evan Broderbe554312013-06-27 00:05:25 -07004382 /* The rest of this logic is based on RFC 6125, section 6.4.3
4383 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4384
Emeric Bruna848dae2013-10-08 11:27:28 +02004385 pattern_wildcard = NULL;
4386 pattern_left_label_end = pattern;
4387 while (*pattern_left_label_end != '.') {
4388 switch (*pattern_left_label_end) {
4389 case 0:
4390 /* End of label not found */
4391 return 0;
4392 case '*':
4393 /* If there is more than one wildcards */
4394 if (pattern_wildcard)
4395 return 0;
4396 pattern_wildcard = pattern_left_label_end;
4397 break;
4398 }
4399 pattern_left_label_end++;
4400 }
4401
4402 /* If it's not trivial and there is no wildcard, it can't
4403 * match */
4404 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004405 return 0;
4406
4407 /* Make sure all labels match except the leftmost */
4408 hostname_left_label_end = strchr(hostname, '.');
4409 if (!hostname_left_label_end
4410 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4411 return 0;
4412
4413 /* Make sure the leftmost label of the hostname is long enough
4414 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004415 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004416 return 0;
4417
4418 /* Finally compare the string on either side of the
4419 * wildcard */
4420 prefixlen = pattern_wildcard - pattern;
4421 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004422 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4423 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004424 return 0;
4425
4426 return 1;
4427}
4428
4429static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4430{
4431 SSL *ssl;
4432 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004433 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004434 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004435
4436 int depth;
4437 X509 *cert;
4438 STACK_OF(GENERAL_NAME) *alt_names;
4439 int i;
4440 X509_NAME *cert_subject;
4441 char *str;
4442
4443 if (ok == 0)
4444 return ok;
4445
4446 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004447 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004448
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004449 /* We're checking if the provided hostnames match the desired one. The
4450 * desired hostname comes from the SNI we presented if any, or if not
4451 * provided then it may have been explicitly stated using a "verifyhost"
4452 * directive. If neither is set, we don't care about the name so the
4453 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004454 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004455 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004456 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004457 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004458 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004459 if (!servername)
4460 return ok;
4461 }
Evan Broderbe554312013-06-27 00:05:25 -07004462
4463 /* We only need to verify the CN on the actual server cert,
4464 * not the indirect CAs */
4465 depth = X509_STORE_CTX_get_error_depth(ctx);
4466 if (depth != 0)
4467 return ok;
4468
4469 /* At this point, the cert is *not* OK unless we can find a
4470 * hostname match */
4471 ok = 0;
4472
4473 cert = X509_STORE_CTX_get_current_cert(ctx);
4474 /* It seems like this might happen if verify peer isn't set */
4475 if (!cert)
4476 return ok;
4477
4478 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4479 if (alt_names) {
4480 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4481 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4482 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004483#if OPENSSL_VERSION_NUMBER < 0x00907000L
4484 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4485#else
Evan Broderbe554312013-06-27 00:05:25 -07004486 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004487#endif
Evan Broderbe554312013-06-27 00:05:25 -07004488 ok = ssl_sock_srv_hostcheck(str, servername);
4489 OPENSSL_free(str);
4490 }
4491 }
4492 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004493 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004494 }
4495
4496 cert_subject = X509_get_subject_name(cert);
4497 i = -1;
4498 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4499 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004500 ASN1_STRING *value;
4501 value = X509_NAME_ENTRY_get_data(entry);
4502 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004503 ok = ssl_sock_srv_hostcheck(str, servername);
4504 OPENSSL_free(str);
4505 }
4506 }
4507
Willy Tarreau71d058c2017-07-26 20:09:56 +02004508 /* report the mismatch and indicate if SNI was used or not */
4509 if (!ok && !conn->err_code)
4510 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004511 return ok;
4512}
4513
Emeric Brun94324a42012-10-11 14:00:19 +02004514/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004515int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004516{
Willy Tarreau03209342016-12-22 17:08:28 +01004517 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004518 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004519 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004520 SSL_OP_ALL | /* all known workarounds for bugs */
4521 SSL_OP_NO_SSLv2 |
4522 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004523 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004524 SSL_MODE_ENABLE_PARTIAL_WRITE |
4525 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004526 SSL_MODE_RELEASE_BUFFERS |
4527 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004528 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004529 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004530 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004531 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004532 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004533
Thierry Fournier383085f2013-01-24 14:15:43 +01004534 /* Make sure openssl opens /dev/urandom before the chroot */
4535 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004536 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004537 cfgerr++;
4538 }
4539
Willy Tarreaufce03112015-01-15 21:32:40 +01004540 /* Automatic memory computations need to know we use SSL there */
4541 global.ssl_used_backend = 1;
4542
4543 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004544 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004545 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004546 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4547 curproxy->id, srv->id,
4548 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004549 cfgerr++;
4550 return cfgerr;
4551 }
4552 }
Emeric Brun94324a42012-10-11 14:00:19 +02004553 if (srv->use_ssl)
4554 srv->xprt = &ssl_sock;
4555 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004556 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004557
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004558 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004559 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004560 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4561 proxy_type_str(curproxy), curproxy->id,
4562 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004563 cfgerr++;
4564 return cfgerr;
4565 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004566
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004567 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004568 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4569 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4570 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004571 else
4572 flags = conf_ssl_methods->flags;
4573
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004574 /* Real min and max should be determinate with configuration and openssl's capabilities */
4575 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004576 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004577 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004578 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004579
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004580 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004581 min = max = CONF_TLSV_NONE;
4582 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004583 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004584 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004585 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004586 if (min) {
4587 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004588 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4589 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4590 proxy_type_str(curproxy), curproxy->id, srv->id,
4591 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004592 hole = 0;
4593 }
4594 max = i;
4595 }
4596 else {
4597 min = max = i;
4598 }
4599 }
4600 else {
4601 if (min)
4602 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004603 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004604 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004605 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4606 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004607 cfgerr += 1;
4608 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004609
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004610#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004611 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004612 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004613 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004614 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004615 else
4616 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4617 if (flags & methodVersions[i].flag)
4618 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004619#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004620 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004621 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4622 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004623#endif
4624
4625 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4626 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004627 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004628
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004629#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004630 if (global_ssl.async)
4631 mode |= SSL_MODE_ASYNC;
4632#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004633 SSL_CTX_set_mode(ctx, mode);
4634 srv->ssl_ctx.ctx = ctx;
4635
Emeric Bruna7aa3092012-10-26 12:58:00 +02004636 if (srv->ssl_ctx.client_crt) {
4637 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 +01004638 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4639 proxy_type_str(curproxy), curproxy->id,
4640 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004641 cfgerr++;
4642 }
4643 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 +01004644 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4645 proxy_type_str(curproxy), curproxy->id,
4646 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004647 cfgerr++;
4648 }
4649 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004650 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4651 proxy_type_str(curproxy), curproxy->id,
4652 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004653 cfgerr++;
4654 }
4655 }
Emeric Brun94324a42012-10-11 14:00:19 +02004656
Emeric Brun850efd52014-01-29 12:24:34 +01004657 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4658 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004659 switch (srv->ssl_ctx.verify) {
4660 case SSL_SOCK_VERIFY_NONE:
4661 verify = SSL_VERIFY_NONE;
4662 break;
4663 case SSL_SOCK_VERIFY_REQUIRED:
4664 verify = SSL_VERIFY_PEER;
4665 break;
4666 }
Evan Broderbe554312013-06-27 00:05:25 -07004667 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004668 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004669 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004670 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004671 if (srv->ssl_ctx.ca_file) {
4672 /* load CAfile to verify */
4673 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004674 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4675 curproxy->id, srv->id,
4676 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004677 cfgerr++;
4678 }
4679 }
Emeric Brun850efd52014-01-29 12:24:34 +01004680 else {
4681 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004682 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",
4683 curproxy->id, srv->id,
4684 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004685 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004686 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4687 curproxy->id, srv->id,
4688 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004689 cfgerr++;
4690 }
Emeric Brunef42d922012-10-11 16:11:36 +02004691#ifdef X509_V_FLAG_CRL_CHECK
4692 if (srv->ssl_ctx.crl_file) {
4693 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4694
4695 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004696 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4697 curproxy->id, srv->id,
4698 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004699 cfgerr++;
4700 }
4701 else {
4702 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4703 }
4704 }
4705#endif
4706 }
4707
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004708 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4709 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4710 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004711 if (srv->ssl_ctx.ciphers &&
4712 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004713 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4714 curproxy->id, srv->id,
4715 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004716 cfgerr++;
4717 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004718
4719#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4720 if (srv->ssl_ctx.ciphersuites &&
4721 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4722 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4723 curproxy->id, srv->id,
4724 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4725 cfgerr++;
4726 }
4727#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004728#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4729 if (srv->ssl_ctx.npn_str)
4730 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4731#endif
4732#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4733 if (srv->ssl_ctx.alpn_str)
4734 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4735#endif
4736
Emeric Brun94324a42012-10-11 14:00:19 +02004737
4738 return cfgerr;
4739}
4740
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004741/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004742 * be NULL, in which case nothing is done. Returns the number of errors
4743 * encountered.
4744 */
Willy Tarreau03209342016-12-22 17:08:28 +01004745int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004746{
4747 struct ebmb_node *node;
4748 struct sni_ctx *sni;
4749 int err = 0;
4750
Willy Tarreaufce03112015-01-15 21:32:40 +01004751 /* Automatic memory computations need to know we use SSL there */
4752 global.ssl_used_frontend = 1;
4753
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004754 /* Make sure openssl opens /dev/urandom before the chroot */
4755 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004756 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004757 err++;
4758 }
4759 /* Create initial_ctx used to start the ssl connection before do switchctx */
4760 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004761 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004762 /* It should not be necessary to call this function, but it's
4763 necessary first to check and move all initialisation related
4764 to initial_ctx in ssl_sock_initial_ctx. */
4765 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4766 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004767 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004768 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004769
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004770 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004771 while (node) {
4772 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004773 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4774 /* only initialize the CTX on its first occurrence and
4775 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004776 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 node = ebmb_next(node);
4778 }
4779
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004780 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004781 while (node) {
4782 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004783 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4784 /* only initialize the CTX on its first occurrence and
4785 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004786 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004787 node = ebmb_next(node);
4788 }
4789 return err;
4790}
4791
Willy Tarreau55d37912016-12-21 23:38:39 +01004792/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4793 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4794 * alerts are directly emitted since the rest of the stack does it below.
4795 */
4796int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4797{
4798 struct proxy *px = bind_conf->frontend;
4799 int alloc_ctx;
4800 int err;
4801
4802 if (!bind_conf->is_ssl) {
4803 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004804 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4805 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004806 }
4807 return 0;
4808 }
4809 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004810 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004811 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4812 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004813 }
4814 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004815 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4816 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004817 return -1;
4818 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004819 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004820 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004821 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004822 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004823 sizeof(*sh_ssl_sess_tree),
4824 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004825 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004826 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4827 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");
4828 else
4829 ha_alert("Unable to allocate SSL session cache.\n");
4830 return -1;
4831 }
4832 /* free block callback */
4833 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4834 /* init the root tree within the extra space */
4835 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4836 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004837 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004838 err = 0;
4839 /* initialize all certificate contexts */
4840 err += ssl_sock_prepare_all_ctx(bind_conf);
4841
4842 /* initialize CA variables if the certificates generation is enabled */
4843 err += ssl_sock_load_ca(bind_conf);
4844
4845 return -err;
4846}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004847
4848/* release ssl context allocated for servers. */
4849void ssl_sock_free_srv_ctx(struct server *srv)
4850{
Olivier Houchardc7566002018-11-20 23:33:50 +01004851#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4852 if (srv->ssl_ctx.alpn_str)
4853 free(srv->ssl_ctx.alpn_str);
4854#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004855#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004856 if (srv->ssl_ctx.npn_str)
4857 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01004858#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004859 if (srv->ssl_ctx.ctx)
4860 SSL_CTX_free(srv->ssl_ctx.ctx);
4861}
4862
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004863/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004864 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4865 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004866void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004867{
4868 struct ebmb_node *node, *back;
4869 struct sni_ctx *sni;
4870
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004871 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004872 while (node) {
4873 sni = ebmb_entry(node, struct sni_ctx, name);
4874 back = ebmb_next(node);
4875 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004876 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004877 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004878 ssl_sock_free_ssl_conf(sni->conf);
4879 free(sni->conf);
4880 sni->conf = NULL;
4881 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004882 free(sni);
4883 node = back;
4884 }
4885
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004886 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004887 while (node) {
4888 sni = ebmb_entry(node, struct sni_ctx, name);
4889 back = ebmb_next(node);
4890 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004891 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004892 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004893 ssl_sock_free_ssl_conf(sni->conf);
4894 free(sni->conf);
4895 sni->conf = NULL;
4896 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004897 free(sni);
4898 node = back;
4899 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004900 SSL_CTX_free(bind_conf->initial_ctx);
4901 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004902 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004903 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004904}
4905
Willy Tarreau795cdab2016-12-22 17:30:54 +01004906/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4907void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4908{
4909 ssl_sock_free_ca(bind_conf);
4910 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004911 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004912 free(bind_conf->ca_sign_file);
4913 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004914 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004915 free(bind_conf->keys_ref->filename);
4916 free(bind_conf->keys_ref->tlskeys);
4917 LIST_DEL(&bind_conf->keys_ref->list);
4918 free(bind_conf->keys_ref);
4919 }
4920 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004921 bind_conf->ca_sign_pass = NULL;
4922 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004923}
4924
Christopher Faulet31af49d2015-06-09 17:29:50 +02004925/* Load CA cert file and private key used to generate certificates */
4926int
Willy Tarreau03209342016-12-22 17:08:28 +01004927ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004928{
Willy Tarreau03209342016-12-22 17:08:28 +01004929 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004930 FILE *fp;
4931 X509 *cacert = NULL;
4932 EVP_PKEY *capkey = NULL;
4933 int err = 0;
4934
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004935 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004936 return err;
4937
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004938#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004939 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004940 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004941 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004942 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004943 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004944#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004945
Christopher Faulet31af49d2015-06-09 17:29:50 +02004946 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004947 ha_alert("Proxy '%s': cannot enable certificate generation, "
4948 "no CA certificate File configured at [%s:%d].\n",
4949 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004950 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004951 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004952
4953 /* read in the CA certificate */
4954 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004955 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4956 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004957 goto load_error;
4958 }
4959 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004960 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4961 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004962 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004963 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004964 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004965 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004966 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4967 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004968 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004969 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004970
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004971 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004972 bind_conf->ca_sign_cert = cacert;
4973 bind_conf->ca_sign_pkey = capkey;
4974 return err;
4975
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004976 read_error:
4977 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004978 if (capkey) EVP_PKEY_free(capkey);
4979 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004980 load_error:
4981 bind_conf->generate_certs = 0;
4982 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004983 return err;
4984}
4985
4986/* Release CA cert and private key used to generate certificated */
4987void
4988ssl_sock_free_ca(struct bind_conf *bind_conf)
4989{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004990 if (bind_conf->ca_sign_pkey)
4991 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4992 if (bind_conf->ca_sign_cert)
4993 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004994 bind_conf->ca_sign_pkey = NULL;
4995 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004996}
4997
Emeric Brun46591952012-05-18 15:47:34 +02004998/*
4999 * This function is called if SSL * context is not yet allocated. The function
5000 * is designed to be called before any other data-layer operation and sets the
5001 * handshake flag on the connection. It is safe to call it multiple times.
5002 * It returns 0 on success and -1 in error case.
5003 */
5004static int ssl_sock_init(struct connection *conn)
5005{
5006 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005007 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005008 return 0;
5009
Willy Tarreau3c728722014-01-23 13:50:42 +01005010 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005011 return 0;
5012
Willy Tarreau20879a02012-12-03 16:32:10 +01005013 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5014 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005015 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005016 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005017
Emeric Brun46591952012-05-18 15:47:34 +02005018 /* If it is in client mode initiate SSL session
5019 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005020 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005021 int may_retry = 1;
5022
5023 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005024 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005025 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005026 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005027 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005028 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005029 goto retry_connect;
5030 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005031 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005032 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005033 }
Emeric Brun46591952012-05-18 15:47:34 +02005034
Emeric Brun46591952012-05-18 15:47:34 +02005035 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005036 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005037 SSL_free(conn->xprt_ctx);
5038 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005039 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005040 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005041 goto retry_connect;
5042 }
Emeric Brun55476152014-11-12 17:35:37 +01005043 conn->err_code = CO_ER_SSL_NO_MEM;
5044 return -1;
5045 }
Emeric Brun46591952012-05-18 15:47:34 +02005046
Evan Broderbe554312013-06-27 00:05:25 -07005047 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005048 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005049 SSL_free(conn->xprt_ctx);
5050 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005051 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005052 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005053 goto retry_connect;
5054 }
Emeric Brun55476152014-11-12 17:35:37 +01005055 conn->err_code = CO_ER_SSL_NO_MEM;
5056 return -1;
5057 }
5058
5059 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005060 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5061 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5062 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5063 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005064 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005065 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5066 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005067 } else if (sess) {
5068 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005069 }
5070 }
Evan Broderbe554312013-06-27 00:05:25 -07005071
Emeric Brun46591952012-05-18 15:47:34 +02005072 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005073 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005074
Emeric Brun7ad43e72018-10-10 14:51:02 +02005075 HA_ATOMIC_ADD(&sslconns, 1);
5076 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005077 return 0;
5078 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005079 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005080 int may_retry = 1;
5081
5082 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005083 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005084 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005085 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005086 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005087 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005088 goto retry_accept;
5089 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005090 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005091 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005092 }
Emeric Brun46591952012-05-18 15:47:34 +02005093
Emeric Brun46591952012-05-18 15:47:34 +02005094 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005095 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005096 SSL_free(conn->xprt_ctx);
5097 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005098 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005099 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005100 goto retry_accept;
5101 }
Emeric Brun55476152014-11-12 17:35:37 +01005102 conn->err_code = CO_ER_SSL_NO_MEM;
5103 return -1;
5104 }
Emeric Brun46591952012-05-18 15:47:34 +02005105
Emeric Brune1f38db2012-09-03 20:36:47 +02005106 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005107 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005108 SSL_free(conn->xprt_ctx);
5109 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005110 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005111 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005112 goto retry_accept;
5113 }
Emeric Brun55476152014-11-12 17:35:37 +01005114 conn->err_code = CO_ER_SSL_NO_MEM;
5115 return -1;
5116 }
5117
5118 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005119
Emeric Brun46591952012-05-18 15:47:34 +02005120 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005121 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005122#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005123 conn->flags |= CO_FL_EARLY_SSL_HS;
5124#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005125
Emeric Brun7ad43e72018-10-10 14:51:02 +02005126 HA_ATOMIC_ADD(&sslconns, 1);
5127 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005128 return 0;
5129 }
5130 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005131 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005132 return -1;
5133}
5134
5135
5136/* This is the callback which is used when an SSL handshake is pending. It
5137 * updates the FD status if it wants some polling before being called again.
5138 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5139 * otherwise it returns non-zero and removes itself from the connection's
5140 * flags (the bit is provided in <flag> by the caller).
5141 */
5142int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5143{
5144 int ret;
5145
Willy Tarreau3c728722014-01-23 13:50:42 +01005146 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005147 return 0;
5148
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005149 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005150 goto out_error;
5151
Olivier Houchardc2aae742017-09-22 18:26:28 +02005152#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5153 /*
5154 * Check if we have early data. If we do, we have to read them
5155 * before SSL_do_handshake() is called, And there's no way to
5156 * detect early data, except to try to read them
5157 */
5158 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5159 size_t read_data;
5160
5161 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5162 1, &read_data);
5163 if (ret == SSL_READ_EARLY_DATA_ERROR)
5164 goto check_error;
5165 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5166 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5167 return 1;
5168 } else
5169 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5170 }
5171#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005172 /* If we use SSL_do_handshake to process a reneg initiated by
5173 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5174 * Usually SSL_write and SSL_read are used and process implicitly
5175 * the reneg handshake.
5176 * Here we use SSL_peek as a workaround for reneg.
5177 */
5178 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5179 char c;
5180
5181 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5182 if (ret <= 0) {
5183 /* handshake may have not been completed, let's find why */
5184 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005185
Emeric Brun674b7432012-11-08 19:21:55 +01005186 if (ret == SSL_ERROR_WANT_WRITE) {
5187 /* SSL handshake needs to write, L4 connection may not be ready */
5188 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005189 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005190 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005191 return 0;
5192 }
5193 else if (ret == SSL_ERROR_WANT_READ) {
5194 /* handshake may have been completed but we have
5195 * no more data to read.
5196 */
5197 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5198 ret = 1;
5199 goto reneg_ok;
5200 }
5201 /* SSL handshake needs to read, L4 connection is ready */
5202 if (conn->flags & CO_FL_WAIT_L4_CONN)
5203 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5204 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005205 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005206 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005207 return 0;
5208 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005209#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005210 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005211 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005212 return 0;
5213 }
5214#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005215 else if (ret == SSL_ERROR_SYSCALL) {
5216 /* if errno is null, then connection was successfully established */
5217 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5218 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005219 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005220#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005221 conn->err_code = CO_ER_SSL_HANDSHAKE;
5222#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005223 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005224#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005225 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5226 empty_handshake = state == TLS_ST_BEFORE;
5227#else
5228 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5229#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005230 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005231 if (!errno) {
5232 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5233 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5234 else
5235 conn->err_code = CO_ER_SSL_EMPTY;
5236 }
5237 else {
5238 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5239 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5240 else
5241 conn->err_code = CO_ER_SSL_ABORT;
5242 }
5243 }
5244 else {
5245 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5246 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005247 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005248 conn->err_code = CO_ER_SSL_HANDSHAKE;
5249 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005250#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005251 }
Emeric Brun674b7432012-11-08 19:21:55 +01005252 goto out_error;
5253 }
5254 else {
5255 /* Fail on all other handshake errors */
5256 /* Note: OpenSSL may leave unread bytes in the socket's
5257 * buffer, causing an RST to be emitted upon close() on
5258 * TCP sockets. We first try to drain possibly pending
5259 * data to avoid this as much as possible.
5260 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005261 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005262 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005263 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5264 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005265 goto out_error;
5266 }
5267 }
5268 /* read some data: consider handshake completed */
5269 goto reneg_ok;
5270 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005271 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005272check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005273 if (ret != 1) {
5274 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005275 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005276
5277 if (ret == SSL_ERROR_WANT_WRITE) {
5278 /* SSL handshake needs to write, L4 connection may not be ready */
5279 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005280 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005281 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005282 return 0;
5283 }
5284 else if (ret == SSL_ERROR_WANT_READ) {
5285 /* SSL handshake needs to read, L4 connection is ready */
5286 if (conn->flags & CO_FL_WAIT_L4_CONN)
5287 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5288 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005289 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005290 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005291 return 0;
5292 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005293#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005294 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005295 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005296 return 0;
5297 }
5298#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005299 else if (ret == SSL_ERROR_SYSCALL) {
5300 /* if errno is null, then connection was successfully established */
5301 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5302 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005303 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005304#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005305 conn->err_code = CO_ER_SSL_HANDSHAKE;
5306#else
5307 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005308#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005309 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5310 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005311#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005312 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005313#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005314 if (empty_handshake) {
5315 if (!errno) {
5316 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5317 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5318 else
5319 conn->err_code = CO_ER_SSL_EMPTY;
5320 }
5321 else {
5322 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5323 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5324 else
5325 conn->err_code = CO_ER_SSL_ABORT;
5326 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005327 }
5328 else {
5329 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5330 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5331 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005332 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005333 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005334#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005335 }
Willy Tarreau89230192012-09-28 20:22:13 +02005336 goto out_error;
5337 }
Emeric Brun46591952012-05-18 15:47:34 +02005338 else {
5339 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005340 /* Note: OpenSSL may leave unread bytes in the socket's
5341 * buffer, causing an RST to be emitted upon close() on
5342 * TCP sockets. We first try to drain possibly pending
5343 * data to avoid this as much as possible.
5344 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005345 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005346 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005347 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5348 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005349 goto out_error;
5350 }
5351 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005352#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5353 else {
5354 /*
5355 * If the server refused the early data, we have to send a
5356 * 425 to the client, as we no longer have the data to sent
5357 * them again.
5358 */
5359 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5360 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5361 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5362 goto out_error;
5363 }
5364 }
5365 }
5366#endif
5367
Emeric Brun46591952012-05-18 15:47:34 +02005368
Emeric Brun674b7432012-11-08 19:21:55 +01005369reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005370
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005371#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005372 /* ASYNC engine API doesn't support moving read/write
5373 * buffers. So we disable ASYNC mode right after
5374 * the handshake to avoid buffer oveflows.
5375 */
5376 if (global_ssl.async)
5377 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5378#endif
Emeric Brun46591952012-05-18 15:47:34 +02005379 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005380 if (!SSL_session_reused(conn->xprt_ctx)) {
5381 if (objt_server(conn->target)) {
5382 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5383 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5384 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005385 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005386 else {
5387 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5388 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5389 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5390 }
Emeric Brun46591952012-05-18 15:47:34 +02005391 }
5392
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005393#ifdef OPENSSL_IS_BORINGSSL
5394 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5395 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5396#endif
Emeric Brun46591952012-05-18 15:47:34 +02005397 /* The connection is now established at both layers, it's time to leave */
5398 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5399 return 1;
5400
5401 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005402 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005403 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005404 ERR_clear_error();
5405
Emeric Brun9fa89732012-10-04 17:09:56 +02005406 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005407 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5408 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5409 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005410 }
5411
Emeric Brun46591952012-05-18 15:47:34 +02005412 /* Fail on all other handshake errors */
5413 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005414 if (!conn->err_code)
5415 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005416 return 0;
5417}
5418
5419/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005420 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005421 * buffer wraps, in which case a second call may be performed. The connection's
5422 * flags are updated with whatever special event is detected (error, read0,
5423 * empty). The caller is responsible for taking care of those events and
5424 * avoiding the call if inappropriate. The function does not call the
5425 * connection's polling update function, so the caller is responsible for this.
5426 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005427static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005428{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005429 ssize_t ret;
5430 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005431
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005432 conn_refresh_polling_flags(conn);
5433
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005434 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005435 goto out_error;
5436
5437 if (conn->flags & CO_FL_HANDSHAKE)
5438 /* a handshake was requested */
5439 return 0;
5440
Emeric Brun46591952012-05-18 15:47:34 +02005441 /* read the largest possible block. For this, we perform only one call
5442 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5443 * in which case we accept to do it once again. A new attempt is made on
5444 * EINTR too.
5445 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005446 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005447 int need_out = 0;
5448
Willy Tarreau591d4452018-06-15 17:21:00 +02005449 try = b_contig_space(buf);
5450 if (!try)
5451 break;
5452
Willy Tarreauabf08d92014-01-14 11:31:27 +01005453 if (try > count)
5454 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005455
Olivier Houchardc2aae742017-09-22 18:26:28 +02005456 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5457 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005458 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005459 done++;
5460 try--;
5461 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005462 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005463 conn->tmp_early_data = -1;
5464 continue;
5465 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005466
Olivier Houchardc2aae742017-09-22 18:26:28 +02005467#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5468 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5469 size_t read_length;
5470
5471 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005472 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005473 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5474 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005475 conn->flags |= CO_FL_EARLY_DATA;
5476 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5477 ret == SSL_READ_EARLY_DATA_FINISH) {
5478 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5479 /*
5480 * We're done reading the early data,
5481 * let's make the handshake
5482 */
5483 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5484 conn->flags |= CO_FL_SSL_WAIT_HS;
5485 need_out = 1;
5486 if (read_length == 0)
5487 break;
5488 }
5489 ret = read_length;
5490 }
5491 } else
5492#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005493 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005494#ifdef OPENSSL_IS_BORINGSSL
5495 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5496 if (SSL_in_early_data(conn->xprt_ctx)) {
5497 if (ret > 0)
5498 conn->flags |= CO_FL_EARLY_DATA;
5499 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005500 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005501 }
5502 }
5503#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005504 if (conn->flags & CO_FL_ERROR) {
5505 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005506 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005507 }
Emeric Brun46591952012-05-18 15:47:34 +02005508 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005509 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005510 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005511 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005512 }
Emeric Brun46591952012-05-18 15:47:34 +02005513 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005514 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005515 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005516 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005517 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005518 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005519#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005520 /* Async mode can be re-enabled, because we're leaving data state.*/
5521 if (global_ssl.async)
5522 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5523#endif
Emeric Brun46591952012-05-18 15:47:34 +02005524 break;
5525 }
5526 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005527 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5528 /* handshake is running, and it may need to re-enable read */
5529 conn->flags |= CO_FL_SSL_WAIT_HS;
5530 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005531#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005532 /* Async mode can be re-enabled, because we're leaving data state.*/
5533 if (global_ssl.async)
5534 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5535#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005536 break;
5537 }
Emeric Brun46591952012-05-18 15:47:34 +02005538 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005539 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005540 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005541 } else if (ret == SSL_ERROR_ZERO_RETURN)
5542 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005543 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5544 * stack before shutting down the connection for
5545 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005546 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5547 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005548 /* otherwise it's a real error */
5549 goto out_error;
5550 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005551 if (need_out)
5552 break;
Emeric Brun46591952012-05-18 15:47:34 +02005553 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005554 leave:
5555 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005556 return done;
5557
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005558 clear_ssl_error:
5559 /* Clear openssl global errors stack */
5560 ssl_sock_dump_errors(conn);
5561 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005562 read0:
5563 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005564 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005565
Emeric Brun46591952012-05-18 15:47:34 +02005566 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005567 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005568 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005569 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005570 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005571 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005572}
5573
5574
Willy Tarreau787db9a2018-06-14 18:31:46 +02005575/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5576 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5577 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005578 * Only one call to send() is performed, unless the buffer wraps, in which case
5579 * a second call may be performed. The connection's flags are updated with
5580 * whatever special event is detected (error, empty). The caller is responsible
5581 * for taking care of those events and avoiding the call if inappropriate. The
5582 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005583 * is responsible for this. The buffer's output is not adjusted, it's up to the
5584 * caller to take care of this. It's up to the caller to update the buffer's
5585 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005586 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005587static 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 +02005588{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005589 ssize_t ret;
5590 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005591
5592 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005593 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005594
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005595 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005596 goto out_error;
5597
5598 if (conn->flags & CO_FL_HANDSHAKE)
5599 /* a handshake was requested */
5600 return 0;
5601
5602 /* send the largest possible block. For this we perform only one call
5603 * to send() unless the buffer wraps and we exactly fill the first hunk,
5604 * in which case we accept to do it once again.
5605 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005606 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005607#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5608 size_t written_data;
5609#endif
5610
Willy Tarreau787db9a2018-06-14 18:31:46 +02005611 try = b_contig_data(buf, done);
5612 if (try > count)
5613 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005614
Willy Tarreau7bed9452014-02-02 02:00:24 +01005615 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005616 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005617 global_ssl.max_record && try > global_ssl.max_record) {
5618 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005619 }
5620 else {
5621 /* we need to keep the information about the fact that
5622 * we're not limiting the upcoming send(), because if it
5623 * fails, we'll have to retry with at least as many data.
5624 */
5625 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5626 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005627
Olivier Houchardc2aae742017-09-22 18:26:28 +02005628#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5629 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5630 unsigned int max_early;
5631
Olivier Houchard522eea72017-11-03 16:27:47 +01005632 if (objt_listener(conn->target))
5633 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5634 else {
5635 if (SSL_get0_session(conn->xprt_ctx))
5636 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5637 else
5638 max_early = 0;
5639 }
5640
Olivier Houchard90084a12017-11-23 18:21:29 +01005641 if (try + conn->sent_early_data > max_early) {
5642 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005643 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005644 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5645 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005646 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005647 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005648 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005649 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005650 if (ret == 1) {
5651 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005652 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005653 if (objt_server(conn->target)) {
5654 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5655 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5656 }
5657
Olivier Houchardc2aae742017-09-22 18:26:28 +02005658 }
5659
5660 } else
5661#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005662 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005663
Emeric Brune1f38db2012-09-03 20:36:47 +02005664 if (conn->flags & CO_FL_ERROR) {
5665 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005666 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005667 }
Emeric Brun46591952012-05-18 15:47:34 +02005668 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005669 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005670 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005671 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005672 }
5673 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005674 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005675
Emeric Brun46591952012-05-18 15:47:34 +02005676 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005677 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5678 /* handshake is running, and it may need to re-enable write */
5679 conn->flags |= CO_FL_SSL_WAIT_HS;
5680 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005681#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005682 /* Async mode can be re-enabled, because we're leaving data state.*/
5683 if (global_ssl.async)
5684 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5685#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005686 break;
5687 }
Emeric Brun46591952012-05-18 15:47:34 +02005688 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005689 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005690 break;
5691 }
5692 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005693 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005694 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005695 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005696#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005697 /* Async mode can be re-enabled, because we're leaving data state.*/
5698 if (global_ssl.async)
5699 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5700#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005701 break;
5702 }
Emeric Brun46591952012-05-18 15:47:34 +02005703 goto out_error;
5704 }
5705 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005706 leave:
5707 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005708 return done;
5709
5710 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005711 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005712 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005713 ERR_clear_error();
5714
Emeric Brun46591952012-05-18 15:47:34 +02005715 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005716 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005717}
5718
Emeric Brun46591952012-05-18 15:47:34 +02005719static void ssl_sock_close(struct connection *conn) {
5720
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005721 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005722#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005723 if (global_ssl.async) {
5724 OSSL_ASYNC_FD all_fd[32], afd;
5725 size_t num_all_fds = 0;
5726 int i;
5727
5728 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5729 if (num_all_fds > 32) {
5730 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5731 return;
5732 }
5733
5734 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5735
5736 /* If an async job is pending, we must try to
5737 to catch the end using polling before calling
5738 SSL_free */
5739 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5740 for (i=0 ; i < num_all_fds ; i++) {
5741 /* switch on an handler designed to
5742 * handle the SSL_free
5743 */
5744 afd = all_fd[i];
5745 fdtab[afd].iocb = ssl_async_fd_free;
5746 fdtab[afd].owner = conn->xprt_ctx;
5747 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005748 /* To ensure that the fd cache won't be used
5749 * and we'll catch a real RD event.
5750 */
5751 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005752 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005753 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005754 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005755 return;
5756 }
Emeric Brun3854e012017-05-17 20:42:48 +02005757 /* Else we can remove the fds from the fdtab
5758 * and call SSL_free.
5759 * note: we do a fd_remove and not a delete
5760 * because the fd is owned by the engine.
5761 * the engine is responsible to close
5762 */
5763 for (i=0 ; i < num_all_fds ; i++)
5764 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005765 }
5766#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005767 SSL_free(conn->xprt_ctx);
5768 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005769 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005770 }
Emeric Brun46591952012-05-18 15:47:34 +02005771}
5772
5773/* This function tries to perform a clean shutdown on an SSL connection, and in
5774 * any case, flags the connection as reusable if no handshake was in progress.
5775 */
5776static void ssl_sock_shutw(struct connection *conn, int clean)
5777{
5778 if (conn->flags & CO_FL_HANDSHAKE)
5779 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005780 if (!clean)
5781 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005782 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005783 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005784 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005785 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005786 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005787 ERR_clear_error();
5788 }
Emeric Brun46591952012-05-18 15:47:34 +02005789}
5790
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005791/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005792int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005793{
5794 struct pkey_info *pkinfo;
5795 int bits = 0;
5796 int sig = TLSEXT_signature_anonymous;
5797 int len = -1;
5798
5799 if (!ssl_sock_is_ssl(conn))
5800 return 0;
5801
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005802 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005803 if (pkinfo) {
5804 sig = pkinfo->sig;
5805 bits = pkinfo->bits;
5806 } else {
5807 /* multicert and generated cert have no pkey info */
5808 X509 *crt;
5809 EVP_PKEY *pkey;
5810 crt = SSL_get_certificate(conn->xprt_ctx);
5811 if (!crt)
5812 return 0;
5813 pkey = X509_get_pubkey(crt);
5814 if (pkey) {
5815 bits = EVP_PKEY_bits(pkey);
5816 switch(EVP_PKEY_base_id(pkey)) {
5817 case EVP_PKEY_RSA:
5818 sig = TLSEXT_signature_rsa;
5819 break;
5820 case EVP_PKEY_EC:
5821 sig = TLSEXT_signature_ecdsa;
5822 break;
5823 case EVP_PKEY_DSA:
5824 sig = TLSEXT_signature_dsa;
5825 break;
5826 }
5827 EVP_PKEY_free(pkey);
5828 }
5829 }
5830
5831 switch(sig) {
5832 case TLSEXT_signature_rsa:
5833 len = chunk_printf(out, "RSA%d", bits);
5834 break;
5835 case TLSEXT_signature_ecdsa:
5836 len = chunk_printf(out, "EC%d", bits);
5837 break;
5838 case TLSEXT_signature_dsa:
5839 len = chunk_printf(out, "DSA%d", bits);
5840 break;
5841 default:
5842 return 0;
5843 }
5844 if (len < 0)
5845 return 0;
5846 return 1;
5847}
5848
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005849/* used for ppv2 cert signature (can be used for logging) */
5850const char *ssl_sock_get_cert_sig(struct connection *conn)
5851{
5852 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5853 X509 *crt;
5854
5855 if (!ssl_sock_is_ssl(conn))
5856 return NULL;
5857 crt = SSL_get_certificate(conn->xprt_ctx);
5858 if (!crt)
5859 return NULL;
5860 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5861 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5862}
5863
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005864/* used for ppv2 authority */
5865const char *ssl_sock_get_sni(struct connection *conn)
5866{
5867#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5868 if (!ssl_sock_is_ssl(conn))
5869 return NULL;
5870 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5871#else
5872 return 0;
5873#endif
5874}
5875
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005876/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005877const char *ssl_sock_get_cipher_name(struct connection *conn)
5878{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005879 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005880 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005881
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005882 return SSL_get_cipher_name(conn->xprt_ctx);
5883}
5884
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005885/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005886const char *ssl_sock_get_proto_version(struct connection *conn)
5887{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005888 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005889 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005890
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005891 return SSL_get_version(conn->xprt_ctx);
5892}
5893
Willy Tarreau8d598402012-10-22 17:58:39 +02005894/* Extract a serial from a cert, and copy it to a chunk.
5895 * Returns 1 if serial is found and copied, 0 if no serial found and
5896 * -1 if output is not large enough.
5897 */
5898static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005899ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005900{
5901 ASN1_INTEGER *serial;
5902
5903 serial = X509_get_serialNumber(crt);
5904 if (!serial)
5905 return 0;
5906
5907 if (out->size < serial->length)
5908 return -1;
5909
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005910 memcpy(out->area, serial->data, serial->length);
5911 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005912 return 1;
5913}
5914
Emeric Brun43e79582014-10-29 19:03:26 +01005915/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005916 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5917 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005918 */
5919static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005920ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005921{
5922 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005923 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005924
5925 len =i2d_X509(crt, NULL);
5926 if (len <= 0)
5927 return 1;
5928
5929 if (out->size < len)
5930 return -1;
5931
5932 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005933 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005934 return 1;
5935}
5936
Emeric Brunce5ad802012-10-22 14:11:22 +02005937
Willy Tarreau83061a82018-07-13 11:56:34 +02005938/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005939 * Returns 1 if serial is found and copied, 0 if no valid time found
5940 * and -1 if output is not large enough.
5941 */
5942static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005943ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005944{
5945 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5946 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5947
5948 if (gentm->length < 12)
5949 return 0;
5950 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5951 return 0;
5952 if (out->size < gentm->length-2)
5953 return -1;
5954
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005955 memcpy(out->area, gentm->data+2, gentm->length-2);
5956 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005957 return 1;
5958 }
5959 else if (tm->type == V_ASN1_UTCTIME) {
5960 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5961
5962 if (utctm->length < 10)
5963 return 0;
5964 if (utctm->data[0] >= 0x35)
5965 return 0;
5966 if (out->size < utctm->length)
5967 return -1;
5968
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005969 memcpy(out->area, utctm->data, utctm->length);
5970 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005971 return 1;
5972 }
5973
5974 return 0;
5975}
5976
Emeric Brun87855892012-10-17 17:39:35 +02005977/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5978 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5979 */
5980static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005981ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5982 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005983{
5984 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005985 ASN1_OBJECT *obj;
5986 ASN1_STRING *data;
5987 const unsigned char *data_ptr;
5988 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005989 int i, j, n;
5990 int cur = 0;
5991 const char *s;
5992 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005993 int name_count;
5994
5995 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005996
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005997 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005998 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005999 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006000 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006001 else
6002 j = i;
6003
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006004 ne = X509_NAME_get_entry(a, j);
6005 obj = X509_NAME_ENTRY_get_object(ne);
6006 data = X509_NAME_ENTRY_get_data(ne);
6007 data_ptr = ASN1_STRING_get0_data(data);
6008 data_len = ASN1_STRING_length(data);
6009 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006010 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006011 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006012 s = tmp;
6013 }
6014
6015 if (chunk_strcasecmp(entry, s) != 0)
6016 continue;
6017
6018 if (pos < 0)
6019 cur--;
6020 else
6021 cur++;
6022
6023 if (cur != pos)
6024 continue;
6025
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006026 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006027 return -1;
6028
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006029 memcpy(out->area, data_ptr, data_len);
6030 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006031 return 1;
6032 }
6033
6034 return 0;
6035
6036}
6037
6038/* Extract and format full DN from a X509_NAME and copy result into a chunk
6039 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6040 */
6041static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006042ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006043{
6044 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006045 ASN1_OBJECT *obj;
6046 ASN1_STRING *data;
6047 const unsigned char *data_ptr;
6048 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006049 int i, n, ln;
6050 int l = 0;
6051 const char *s;
6052 char *p;
6053 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006054 int name_count;
6055
6056
6057 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006058
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006059 out->data = 0;
6060 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006061 for (i = 0; i < name_count; i++) {
6062 ne = X509_NAME_get_entry(a, i);
6063 obj = X509_NAME_ENTRY_get_object(ne);
6064 data = X509_NAME_ENTRY_get_data(ne);
6065 data_ptr = ASN1_STRING_get0_data(data);
6066 data_len = ASN1_STRING_length(data);
6067 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006068 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006069 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006070 s = tmp;
6071 }
6072 ln = strlen(s);
6073
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006074 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006075 if (l > out->size)
6076 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006077 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006078
6079 *(p++)='/';
6080 memcpy(p, s, ln);
6081 p += ln;
6082 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006083 memcpy(p, data_ptr, data_len);
6084 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006085 }
6086
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006087 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006088 return 0;
6089
6090 return 1;
6091}
6092
Willy Tarreau119a4082016-12-22 21:58:38 +01006093/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6094 * to disable SNI.
6095 */
Willy Tarreau63076412015-07-10 11:33:32 +02006096void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6097{
6098#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006099 char *prev_name;
6100
Willy Tarreau63076412015-07-10 11:33:32 +02006101 if (!ssl_sock_is_ssl(conn))
6102 return;
6103
Willy Tarreau119a4082016-12-22 21:58:38 +01006104 /* if the SNI changes, we must destroy the reusable context so that a
6105 * new connection will present a new SNI. As an optimization we could
6106 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6107 * server.
6108 */
6109 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6110 if ((!prev_name && hostname) ||
6111 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6112 SSL_set_session(conn->xprt_ctx, NULL);
6113
Willy Tarreau63076412015-07-10 11:33:32 +02006114 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6115#endif
6116}
6117
Emeric Brun0abf8362014-06-24 18:26:41 +02006118/* Extract peer certificate's common name into the chunk dest
6119 * Returns
6120 * the len of the extracted common name
6121 * or 0 if no CN found in DN
6122 * or -1 on error case (i.e. no peer certificate)
6123 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006124int ssl_sock_get_remote_common_name(struct connection *conn,
6125 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006126{
6127 X509 *crt = NULL;
6128 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006129 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006130 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006131 .area = (char *)&find_cn,
6132 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006133 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006134 int result = -1;
David Safb76832014-05-08 23:42:08 -04006135
6136 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006137 goto out;
David Safb76832014-05-08 23:42:08 -04006138
6139 /* SSL_get_peer_certificate, it increase X509 * ref count */
6140 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6141 if (!crt)
6142 goto out;
6143
6144 name = X509_get_subject_name(crt);
6145 if (!name)
6146 goto out;
David Safb76832014-05-08 23:42:08 -04006147
Emeric Brun0abf8362014-06-24 18:26:41 +02006148 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6149out:
David Safb76832014-05-08 23:42:08 -04006150 if (crt)
6151 X509_free(crt);
6152
6153 return result;
6154}
6155
Dave McCowan328fb582014-07-30 10:39:13 -04006156/* returns 1 if client passed a certificate for this session, 0 if not */
6157int ssl_sock_get_cert_used_sess(struct connection *conn)
6158{
6159 X509 *crt = NULL;
6160
6161 if (!ssl_sock_is_ssl(conn))
6162 return 0;
6163
6164 /* SSL_get_peer_certificate, it increase X509 * ref count */
6165 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6166 if (!crt)
6167 return 0;
6168
6169 X509_free(crt);
6170 return 1;
6171}
6172
6173/* returns 1 if client passed a certificate for this connection, 0 if not */
6174int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006175{
6176 if (!ssl_sock_is_ssl(conn))
6177 return 0;
6178
6179 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6180}
6181
6182/* returns result from SSL verify */
6183unsigned int ssl_sock_get_verify_result(struct connection *conn)
6184{
6185 if (!ssl_sock_is_ssl(conn))
6186 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6187
6188 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6189}
6190
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006191/* Returns the application layer protocol name in <str> and <len> when known.
6192 * Zero is returned if the protocol name was not found, otherwise non-zero is
6193 * returned. The string is allocated in the SSL context and doesn't have to be
6194 * freed by the caller. NPN is also checked if available since older versions
6195 * of openssl (1.0.1) which are more common in field only support this one.
6196 */
6197static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6198{
6199 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6200 return 0;
6201
6202 *str = NULL;
6203
6204#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6205 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6206 if (*str)
6207 return 1;
6208#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006209#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006210 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6211 if (*str)
6212 return 1;
6213#endif
6214 return 0;
6215}
6216
Willy Tarreau7875d092012-09-10 08:20:03 +02006217/***** Below are some sample fetching functions for ACL/patterns *****/
6218
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006219static int
6220smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6221{
6222 struct connection *conn;
6223
6224 conn = objt_conn(smp->sess->origin);
6225 if (!conn || conn->xprt != &ssl_sock)
6226 return 0;
6227
6228 smp->flags = 0;
6229 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006230 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6231 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006232
6233 return 1;
6234}
6235
Emeric Brune64aef12012-09-21 13:15:06 +02006236/* boolean, returns true if client cert was present */
6237static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006238smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006239{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006240 struct connection *conn;
6241
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006242 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006243 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006244 return 0;
6245
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006246 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006247 smp->flags |= SMP_F_MAY_CHANGE;
6248 return 0;
6249 }
6250
6251 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006252 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006253 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006254
6255 return 1;
6256}
6257
Emeric Brun43e79582014-10-29 19:03:26 +01006258/* binary, returns a certificate in a binary chunk (der/raw).
6259 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6260 * should be use.
6261 */
6262static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006263smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006264{
6265 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6266 X509 *crt = NULL;
6267 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006268 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006269 struct connection *conn;
6270
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006271 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006272 if (!conn || conn->xprt != &ssl_sock)
6273 return 0;
6274
6275 if (!(conn->flags & CO_FL_CONNECTED)) {
6276 smp->flags |= SMP_F_MAY_CHANGE;
6277 return 0;
6278 }
6279
6280 if (cert_peer)
6281 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6282 else
6283 crt = SSL_get_certificate(conn->xprt_ctx);
6284
6285 if (!crt)
6286 goto out;
6287
6288 smp_trash = get_trash_chunk();
6289 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6290 goto out;
6291
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006292 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006293 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006294 ret = 1;
6295out:
6296 /* SSL_get_peer_certificate, it increase X509 * ref count */
6297 if (cert_peer && crt)
6298 X509_free(crt);
6299 return ret;
6300}
6301
Emeric Brunba841a12014-04-30 17:05:08 +02006302/* binary, returns serial of certificate in a binary chunk.
6303 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6304 * should be use.
6305 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006306static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006307smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006308{
Emeric Brunba841a12014-04-30 17:05:08 +02006309 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006310 X509 *crt = NULL;
6311 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006312 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006313 struct connection *conn;
6314
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006315 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006316 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006317 return 0;
6318
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006319 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006320 smp->flags |= SMP_F_MAY_CHANGE;
6321 return 0;
6322 }
6323
Emeric Brunba841a12014-04-30 17:05:08 +02006324 if (cert_peer)
6325 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6326 else
6327 crt = SSL_get_certificate(conn->xprt_ctx);
6328
Willy Tarreau8d598402012-10-22 17:58:39 +02006329 if (!crt)
6330 goto out;
6331
Willy Tarreau47ca5452012-12-23 20:22:19 +01006332 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006333 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6334 goto out;
6335
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006336 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006337 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006338 ret = 1;
6339out:
Emeric Brunba841a12014-04-30 17:05:08 +02006340 /* SSL_get_peer_certificate, it increase X509 * ref count */
6341 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006342 X509_free(crt);
6343 return ret;
6344}
Emeric Brune64aef12012-09-21 13:15:06 +02006345
Emeric Brunba841a12014-04-30 17:05:08 +02006346/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6347 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6348 * should be use.
6349 */
James Votha051b4a2013-05-14 20:37:59 +02006350static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006351smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006352{
Emeric Brunba841a12014-04-30 17:05:08 +02006353 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006354 X509 *crt = NULL;
6355 const EVP_MD *digest;
6356 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006357 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006358 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006359
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006360 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006361 if (!conn || conn->xprt != &ssl_sock)
6362 return 0;
6363
6364 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006365 smp->flags |= SMP_F_MAY_CHANGE;
6366 return 0;
6367 }
6368
Emeric Brunba841a12014-04-30 17:05:08 +02006369 if (cert_peer)
6370 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6371 else
6372 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006373 if (!crt)
6374 goto out;
6375
6376 smp_trash = get_trash_chunk();
6377 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006378 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6379 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006380
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006381 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006382 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006383 ret = 1;
6384out:
Emeric Brunba841a12014-04-30 17:05:08 +02006385 /* SSL_get_peer_certificate, it increase X509 * ref count */
6386 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006387 X509_free(crt);
6388 return ret;
6389}
6390
Emeric Brunba841a12014-04-30 17:05:08 +02006391/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6392 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6393 * should be use.
6394 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006395static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006396smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006397{
Emeric Brunba841a12014-04-30 17:05:08 +02006398 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006399 X509 *crt = NULL;
6400 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006401 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006402 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006403
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006404 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006405 if (!conn || conn->xprt != &ssl_sock)
6406 return 0;
6407
6408 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006409 smp->flags |= SMP_F_MAY_CHANGE;
6410 return 0;
6411 }
6412
Emeric Brunba841a12014-04-30 17:05:08 +02006413 if (cert_peer)
6414 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6415 else
6416 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006417 if (!crt)
6418 goto out;
6419
Willy Tarreau47ca5452012-12-23 20:22:19 +01006420 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006421 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6422 goto out;
6423
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006424 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006425 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006426 ret = 1;
6427out:
Emeric Brunba841a12014-04-30 17:05:08 +02006428 /* SSL_get_peer_certificate, it increase X509 * ref count */
6429 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006430 X509_free(crt);
6431 return ret;
6432}
6433
Emeric Brunba841a12014-04-30 17:05:08 +02006434/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6435 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6436 * should be use.
6437 */
Emeric Brun87855892012-10-17 17:39:35 +02006438static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006439smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006440{
Emeric Brunba841a12014-04-30 17:05:08 +02006441 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006442 X509 *crt = NULL;
6443 X509_NAME *name;
6444 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006445 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006446 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006447
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006448 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006449 if (!conn || conn->xprt != &ssl_sock)
6450 return 0;
6451
6452 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006453 smp->flags |= SMP_F_MAY_CHANGE;
6454 return 0;
6455 }
6456
Emeric Brunba841a12014-04-30 17:05:08 +02006457 if (cert_peer)
6458 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6459 else
6460 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006461 if (!crt)
6462 goto out;
6463
6464 name = X509_get_issuer_name(crt);
6465 if (!name)
6466 goto out;
6467
Willy Tarreau47ca5452012-12-23 20:22:19 +01006468 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006469 if (args && args[0].type == ARGT_STR) {
6470 int pos = 1;
6471
6472 if (args[1].type == ARGT_SINT)
6473 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006474
6475 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6476 goto out;
6477 }
6478 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6479 goto out;
6480
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006481 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006482 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006483 ret = 1;
6484out:
Emeric Brunba841a12014-04-30 17:05:08 +02006485 /* SSL_get_peer_certificate, it increase X509 * ref count */
6486 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006487 X509_free(crt);
6488 return ret;
6489}
6490
Emeric Brunba841a12014-04-30 17:05:08 +02006491/* string, returns notbefore date in ASN1_UTCTIME format.
6492 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6493 * should be use.
6494 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006495static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006496smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006497{
Emeric Brunba841a12014-04-30 17:05:08 +02006498 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006499 X509 *crt = NULL;
6500 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006501 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006502 struct connection *conn;
6503
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006504 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006505 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006506 return 0;
6507
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006508 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006509 smp->flags |= SMP_F_MAY_CHANGE;
6510 return 0;
6511 }
6512
Emeric Brunba841a12014-04-30 17:05:08 +02006513 if (cert_peer)
6514 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6515 else
6516 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006517 if (!crt)
6518 goto out;
6519
Willy Tarreau47ca5452012-12-23 20:22:19 +01006520 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006521 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6522 goto out;
6523
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006524 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006525 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006526 ret = 1;
6527out:
Emeric Brunba841a12014-04-30 17:05:08 +02006528 /* SSL_get_peer_certificate, it increase X509 * ref count */
6529 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006530 X509_free(crt);
6531 return ret;
6532}
6533
Emeric Brunba841a12014-04-30 17:05:08 +02006534/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6535 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6536 * should be use.
6537 */
Emeric Brun87855892012-10-17 17:39:35 +02006538static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006539smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006540{
Emeric Brunba841a12014-04-30 17:05:08 +02006541 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006542 X509 *crt = NULL;
6543 X509_NAME *name;
6544 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006545 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006546 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006547
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006548 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006549 if (!conn || conn->xprt != &ssl_sock)
6550 return 0;
6551
6552 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006553 smp->flags |= SMP_F_MAY_CHANGE;
6554 return 0;
6555 }
6556
Emeric Brunba841a12014-04-30 17:05:08 +02006557 if (cert_peer)
6558 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6559 else
6560 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006561 if (!crt)
6562 goto out;
6563
6564 name = X509_get_subject_name(crt);
6565 if (!name)
6566 goto out;
6567
Willy Tarreau47ca5452012-12-23 20:22:19 +01006568 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006569 if (args && args[0].type == ARGT_STR) {
6570 int pos = 1;
6571
6572 if (args[1].type == ARGT_SINT)
6573 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006574
6575 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6576 goto out;
6577 }
6578 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6579 goto out;
6580
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006581 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006582 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006583 ret = 1;
6584out:
Emeric Brunba841a12014-04-30 17:05:08 +02006585 /* SSL_get_peer_certificate, it increase X509 * ref count */
6586 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006587 X509_free(crt);
6588 return ret;
6589}
Emeric Brun9143d372012-12-20 15:44:16 +01006590
6591/* integer, returns true if current session use a client certificate */
6592static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006593smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006594{
6595 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006596 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006597
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006598 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006599 if (!conn || conn->xprt != &ssl_sock)
6600 return 0;
6601
6602 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006603 smp->flags |= SMP_F_MAY_CHANGE;
6604 return 0;
6605 }
6606
6607 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006608 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006609 if (crt) {
6610 X509_free(crt);
6611 }
6612
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006613 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006614 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006615 return 1;
6616}
6617
Emeric Brunba841a12014-04-30 17:05:08 +02006618/* integer, returns the certificate version
6619 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6620 * should be use.
6621 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006622static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006623smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006624{
Emeric Brunba841a12014-04-30 17:05:08 +02006625 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006626 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006627 struct connection *conn;
6628
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)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006631 return 0;
6632
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006633 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +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 Bruna7359fd2012-10-17 15:03:11 +02006642 if (!crt)
6643 return 0;
6644
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006645 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006646 /* SSL_get_peer_certificate increase X509 * ref count */
6647 if (cert_peer)
6648 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006649 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006650
6651 return 1;
6652}
6653
Emeric Brunba841a12014-04-30 17:05:08 +02006654/* string, returns the certificate's signature algorithm.
6655 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6656 * should be use.
6657 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006658static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006659smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006660{
Emeric Brunba841a12014-04-30 17:05:08 +02006661 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006662 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006663 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006664 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006665 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006666
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006667 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006668 if (!conn || conn->xprt != &ssl_sock)
6669 return 0;
6670
6671 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006672 smp->flags |= SMP_F_MAY_CHANGE;
6673 return 0;
6674 }
6675
Emeric Brunba841a12014-04-30 17:05:08 +02006676 if (cert_peer)
6677 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6678 else
6679 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006680 if (!crt)
6681 return 0;
6682
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006683 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6684 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006685
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006686 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6687 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006688 /* SSL_get_peer_certificate increase X509 * ref count */
6689 if (cert_peer)
6690 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006691 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006692 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006693
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006694 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006695 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006696 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006697 /* SSL_get_peer_certificate increase X509 * ref count */
6698 if (cert_peer)
6699 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006700
6701 return 1;
6702}
6703
Emeric Brunba841a12014-04-30 17:05:08 +02006704/* string, returns the certificate's key algorithm.
6705 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6706 * should be use.
6707 */
Emeric Brun521a0112012-10-22 12:22:55 +02006708static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006709smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006710{
Emeric Brunba841a12014-04-30 17:05:08 +02006711 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006712 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006713 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006714 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006715 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006716
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006717 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006718 if (!conn || conn->xprt != &ssl_sock)
6719 return 0;
6720
6721 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006722 smp->flags |= SMP_F_MAY_CHANGE;
6723 return 0;
6724 }
6725
Emeric Brunba841a12014-04-30 17:05:08 +02006726 if (cert_peer)
6727 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6728 else
6729 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006730 if (!crt)
6731 return 0;
6732
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006733 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6734 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006735
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006736 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6737 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006738 /* SSL_get_peer_certificate increase X509 * ref count */
6739 if (cert_peer)
6740 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006741 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006742 }
Emeric Brun521a0112012-10-22 12:22:55 +02006743
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006744 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006745 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006746 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006747 if (cert_peer)
6748 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006749
6750 return 1;
6751}
6752
Emeric Brun645ae792014-04-30 14:21:06 +02006753/* boolean, returns true if front conn. transport layer is SSL.
6754 * This function is also usable on backend conn if the fetch keyword 5th
6755 * char is 'b'.
6756 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006757static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006758smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006759{
Emeric Bruneb8def92018-02-19 15:59:48 +01006760 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6761 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006762
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006763 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006764 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006765 return 1;
6766}
6767
Emeric Brun2525b6b2012-10-18 15:59:43 +02006768/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006769static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006770smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006771{
6772#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006773 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006774
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006775 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006776 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006777 conn->xprt_ctx &&
6778 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006779 return 1;
6780#else
6781 return 0;
6782#endif
6783}
6784
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006785/* boolean, returns true if client session has been resumed.
6786 * This function is also usable on backend conn if the fetch keyword 5th
6787 * char is 'b'.
6788 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006789static int
6790smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6791{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006792 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6793 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6794
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006795
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006796 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006797 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006798 conn->xprt_ctx &&
6799 SSL_session_reused(conn->xprt_ctx);
6800 return 1;
6801}
6802
Emeric Brun645ae792014-04-30 14:21:06 +02006803/* string, returns the used cipher if front conn. transport layer is SSL.
6804 * This function is also usable on backend conn if the fetch keyword 5th
6805 * char is 'b'.
6806 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006807static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006808smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006809{
Emeric Bruneb8def92018-02-19 15:59:48 +01006810 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6811 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006812
Willy Tarreaube508f12016-03-10 11:47:01 +01006813 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006814 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006815 return 0;
6816
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006817 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6818 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006819 return 0;
6820
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006821 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006822 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006823 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006824
6825 return 1;
6826}
6827
Emeric Brun645ae792014-04-30 14:21:06 +02006828/* integer, returns the algoritm's keysize if front conn. transport layer
6829 * is SSL.
6830 * This function is also usable on backend conn if the fetch keyword 5th
6831 * char is 'b'.
6832 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006833static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006834smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006835{
Emeric Bruneb8def92018-02-19 15:59:48 +01006836 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6837 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006838 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006839
Emeric Brun589fcad2012-10-16 14:13:26 +02006840 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006841 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006842 return 0;
6843
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006844 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006845 return 0;
6846
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006847 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006848 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006849
6850 return 1;
6851}
6852
Emeric Brun645ae792014-04-30 14:21:06 +02006853/* integer, returns the used keysize if front conn. transport layer is SSL.
6854 * This function is also usable on backend conn if the fetch keyword 5th
6855 * char is 'b'.
6856 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006857static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006858smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006859{
Emeric Bruneb8def92018-02-19 15:59:48 +01006860 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6861 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006862
Emeric Brun589fcad2012-10-16 14:13:26 +02006863 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006864 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6865 return 0;
6866
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006867 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6868 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006869 return 0;
6870
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006871 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006872
6873 return 1;
6874}
6875
Bernard Spil13c53f82018-02-15 13:34:58 +01006876#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006877static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006878smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006879{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006880 struct connection *conn;
6881
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006882 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006883 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006884
Olivier Houchard6b77f492018-11-22 18:18:29 +01006885 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6886 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006887 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6888 return 0;
6889
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006890 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006891 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006892 (const unsigned char **)&smp->data.u.str.area,
6893 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006894
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006895 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006896 return 0;
6897
6898 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006899}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006900#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006901
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006902#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006903static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006904smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006905{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006906 struct connection *conn;
6907
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006908 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006909 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006910
Olivier Houchard6b77f492018-11-22 18:18:29 +01006911 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6912 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6913
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006914 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006915 return 0;
6916
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006917 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006918 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006919 (const unsigned char **)&smp->data.u.str.area,
6920 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006921
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006922 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006923 return 0;
6924
6925 return 1;
6926}
6927#endif
6928
Emeric Brun645ae792014-04-30 14:21:06 +02006929/* string, returns the used protocol if front conn. transport layer is SSL.
6930 * This function is also usable on backend conn if the fetch keyword 5th
6931 * char is 'b'.
6932 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006933static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006934smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006935{
Emeric Bruneb8def92018-02-19 15:59:48 +01006936 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6937 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006938
Emeric Brun589fcad2012-10-16 14:13:26 +02006939 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006940 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6941 return 0;
6942
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006943 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6944 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006945 return 0;
6946
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006947 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006948 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006949 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006950
6951 return 1;
6952}
6953
Willy Tarreau87b09662015-04-03 00:22:06 +02006954/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006955 * This function is also usable on backend conn if the fetch keyword 5th
6956 * char is 'b'.
6957 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006958#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006959static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006960smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006961{
Emeric Bruneb8def92018-02-19 15:59:48 +01006962 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6963 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006964 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006965
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006966 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006967 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006968
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006969 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6970 return 0;
6971
Willy Tarreau192252e2015-04-04 01:47:55 +02006972 ssl_sess = SSL_get_session(conn->xprt_ctx);
6973 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006974 return 0;
6975
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006976 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6977 (unsigned int *)&smp->data.u.str.data);
6978 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006979 return 0;
6980
6981 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006982}
Patrick Hemmer41966772018-04-28 19:15:48 -04006983#endif
6984
Emeric Brunfe68f682012-10-16 14:59:28 +02006985
Patrick Hemmere0275472018-04-28 19:15:51 -04006986#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6987static int
6988smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6989{
6990 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6991 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6992 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006993 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006994
6995 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6996 return 0;
6997
6998 ssl_sess = SSL_get_session(conn->xprt_ctx);
6999 if (!ssl_sess)
7000 return 0;
7001
7002 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007003 data->data = SSL_SESSION_get_master_key(ssl_sess,
7004 (unsigned char *) data->area,
7005 data->size);
7006 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007007 return 0;
7008
7009 smp->flags = 0;
7010 smp->data.type = SMP_T_BIN;
7011 smp->data.u.str = *data;
7012
7013 return 1;
7014}
7015#endif
7016
Patrick Hemmer41966772018-04-28 19:15:48 -04007017#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007018static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007019smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007020{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007021 struct connection *conn;
7022
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007023 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007024 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007025
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007026 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007027 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7028 return 0;
7029
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007030 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7031 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007032 return 0;
7033
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007034 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007035 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007036}
Patrick Hemmer41966772018-04-28 19:15:48 -04007037#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007038
David Sc1ad52e2014-04-08 18:48:47 -04007039static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007040smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7041{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007042 struct connection *conn;
7043 struct ssl_capture *capture;
7044
7045 conn = objt_conn(smp->sess->origin);
7046 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7047 return 0;
7048
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007049 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007050 if (!capture)
7051 return 0;
7052
7053 smp->flags = SMP_F_CONST;
7054 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007055 smp->data.u.str.area = capture->ciphersuite;
7056 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007057 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007058}
7059
7060static int
7061smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7062{
Willy Tarreau83061a82018-07-13 11:56:34 +02007063 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007064
7065 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7066 return 0;
7067
7068 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007069 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007070 smp->data.type = SMP_T_BIN;
7071 smp->data.u.str = *data;
7072 return 1;
7073}
7074
7075static int
7076smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7077{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007078 struct connection *conn;
7079 struct ssl_capture *capture;
7080
7081 conn = objt_conn(smp->sess->origin);
7082 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7083 return 0;
7084
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007085 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007086 if (!capture)
7087 return 0;
7088
7089 smp->data.type = SMP_T_SINT;
7090 smp->data.u.sint = capture->xxh64;
7091 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007092}
7093
7094static int
7095smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7096{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007097#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007098 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007099 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007100
7101 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7102 return 0;
7103
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007104 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007105 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007106 const char *str;
7107 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007108 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007109 uint16_t id = (bin[0] << 8) | bin[1];
7110#if defined(OPENSSL_IS_BORINGSSL)
7111 cipher = SSL_get_cipher_by_value(id);
7112#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007113 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007114 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7115#endif
7116 str = SSL_CIPHER_get_name(cipher);
7117 if (!str || strcmp(str, "(NONE)") == 0)
7118 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007119 else
7120 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7121 }
7122 smp->data.type = SMP_T_STR;
7123 smp->data.u.str = *data;
7124 return 1;
7125#else
7126 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7127#endif
7128}
7129
Patrick Hemmer41966772018-04-28 19:15:48 -04007130#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007131static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007132smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007133{
Emeric Bruneb8def92018-02-19 15:59:48 +01007134 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7135 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007136 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007137 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007138
7139 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007140 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7141 return 0;
7142
7143 if (!(conn->flags & CO_FL_CONNECTED)) {
7144 smp->flags |= SMP_F_MAY_CHANGE;
7145 return 0;
7146 }
7147
7148 finished_trash = get_trash_chunk();
7149 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007150 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7151 finished_trash->area,
7152 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007153 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007154 finished_len = SSL_get_finished(conn->xprt_ctx,
7155 finished_trash->area,
7156 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007157
7158 if (!finished_len)
7159 return 0;
7160
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007161 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007162 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007163 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007164
7165 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007166}
Patrick Hemmer41966772018-04-28 19:15:48 -04007167#endif
David Sc1ad52e2014-04-08 18:48:47 -04007168
Emeric Brun2525b6b2012-10-18 15:59:43 +02007169/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007170static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007171smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007172{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007173 struct connection *conn;
7174
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007175 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007176 if (!conn || conn->xprt != &ssl_sock)
7177 return 0;
7178
7179 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007180 smp->flags = SMP_F_MAY_CHANGE;
7181 return 0;
7182 }
7183
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007184 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007185 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007186 smp->flags = 0;
7187
7188 return 1;
7189}
7190
Emeric Brun2525b6b2012-10-18 15:59:43 +02007191/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007192static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007193smp_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 +02007194{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007195 struct connection *conn;
7196
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007197 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007198 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007199 return 0;
7200
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007201 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007202 smp->flags = SMP_F_MAY_CHANGE;
7203 return 0;
7204 }
7205
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007206 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007207 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007208 smp->flags = 0;
7209
7210 return 1;
7211}
7212
Emeric Brun2525b6b2012-10-18 15:59:43 +02007213/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007214static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007215smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007216{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007217 struct connection *conn;
7218
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007219 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007220 if (!conn || conn->xprt != &ssl_sock)
7221 return 0;
7222
7223 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007224 smp->flags = SMP_F_MAY_CHANGE;
7225 return 0;
7226 }
7227
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007228 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007229 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007230 smp->flags = 0;
7231
7232 return 1;
7233}
7234
Emeric Brun2525b6b2012-10-18 15:59:43 +02007235/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007236static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007237smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007238{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007239 struct connection *conn;
7240
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007241 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007242 if (!conn || conn->xprt != &ssl_sock)
7243 return 0;
7244
7245 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007246 smp->flags = SMP_F_MAY_CHANGE;
7247 return 0;
7248 }
7249
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007250 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007251 return 0;
7252
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007253 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007254 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007255 smp->flags = 0;
7256
7257 return 1;
7258}
7259
Emeric Brunfb510ea2012-10-05 12:00:26 +02007260/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007261static 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 +02007262{
7263 if (!*args[cur_arg + 1]) {
7264 if (err)
7265 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7266 return ERR_ALERT | ERR_FATAL;
7267 }
7268
Willy Tarreauef934602016-12-22 23:12:01 +01007269 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7270 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007271 else
7272 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007273
Emeric Brund94b3fe2012-09-20 18:23:56 +02007274 return 0;
7275}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007276static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7277{
7278 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7279}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007280
Christopher Faulet31af49d2015-06-09 17:29:50 +02007281/* parse the "ca-sign-file" bind keyword */
7282static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7283{
7284 if (!*args[cur_arg + 1]) {
7285 if (err)
7286 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7287 return ERR_ALERT | ERR_FATAL;
7288 }
7289
Willy Tarreauef934602016-12-22 23:12:01 +01007290 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7291 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007292 else
7293 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7294
7295 return 0;
7296}
7297
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007298/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007299static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7300{
7301 if (!*args[cur_arg + 1]) {
7302 if (err)
7303 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7304 return ERR_ALERT | ERR_FATAL;
7305 }
7306 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7307 return 0;
7308}
7309
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007310/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007311static 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 +02007312{
7313 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007314 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007315 return ERR_ALERT | ERR_FATAL;
7316 }
7317
Emeric Brun76d88952012-10-05 15:47:31 +02007318 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007319 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007320 return 0;
7321}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007322static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7323{
7324 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7325}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007326
7327#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7328/* parse the "ciphersuites" bind keyword */
7329static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7330{
7331 if (!*args[cur_arg + 1]) {
7332 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7333 return ERR_ALERT | ERR_FATAL;
7334 }
7335
7336 free(conf->ciphersuites);
7337 conf->ciphersuites = strdup(args[cur_arg + 1]);
7338 return 0;
7339}
7340static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7341{
7342 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7343}
7344#endif
7345
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007346/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007347static 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 +02007348{
Willy Tarreau38011032013-08-13 16:59:39 +02007349 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007350
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007351 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007352 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007353 return ERR_ALERT | ERR_FATAL;
7354 }
7355
Willy Tarreauef934602016-12-22 23:12:01 +01007356 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7357 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007358 memprintf(err, "'%s' : path too long", args[cur_arg]);
7359 return ERR_ALERT | ERR_FATAL;
7360 }
Willy Tarreauef934602016-12-22 23:12:01 +01007361 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007362 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007363 return ERR_ALERT | ERR_FATAL;
7364
7365 return 0;
7366 }
7367
Willy Tarreau03209342016-12-22 17:08:28 +01007368 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007369 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007370
7371 return 0;
7372}
7373
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007374/* parse the "crt-list" bind keyword */
7375static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7376{
7377 if (!*args[cur_arg + 1]) {
7378 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7379 return ERR_ALERT | ERR_FATAL;
7380 }
7381
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007382 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007383 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007384 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007385 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007386
7387 return 0;
7388}
7389
Emeric Brunfb510ea2012-10-05 12:00:26 +02007390/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007391static 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 +02007392{
Emeric Brun051cdab2012-10-02 19:25:50 +02007393#ifndef X509_V_FLAG_CRL_CHECK
7394 if (err)
7395 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7396 return ERR_ALERT | ERR_FATAL;
7397#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007398 if (!*args[cur_arg + 1]) {
7399 if (err)
7400 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7401 return ERR_ALERT | ERR_FATAL;
7402 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007403
Willy Tarreauef934602016-12-22 23:12:01 +01007404 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7405 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007406 else
7407 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007408
Emeric Brun2b58d042012-09-20 17:10:03 +02007409 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007410#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007411}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007412static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7413{
7414 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7415}
Emeric Brun2b58d042012-09-20 17:10:03 +02007416
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007417/* parse the "curves" bind keyword keyword */
7418static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7419{
7420#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7421 if (!*args[cur_arg + 1]) {
7422 if (err)
7423 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7424 return ERR_ALERT | ERR_FATAL;
7425 }
7426 conf->curves = strdup(args[cur_arg + 1]);
7427 return 0;
7428#else
7429 if (err)
7430 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7431 return ERR_ALERT | ERR_FATAL;
7432#endif
7433}
7434static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7435{
7436 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7437}
7438
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007439/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007440static 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 +02007441{
7442#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7443 if (err)
7444 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7445 return ERR_ALERT | ERR_FATAL;
7446#elif defined(OPENSSL_NO_ECDH)
7447 if (err)
7448 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7449 return ERR_ALERT | ERR_FATAL;
7450#else
7451 if (!*args[cur_arg + 1]) {
7452 if (err)
7453 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7454 return ERR_ALERT | ERR_FATAL;
7455 }
7456
7457 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007458
7459 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007460#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007461}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007462static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7463{
7464 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7465}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007466
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007467/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007468static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7469{
7470 int code;
7471 char *p = args[cur_arg + 1];
7472 unsigned long long *ignerr = &conf->crt_ignerr;
7473
7474 if (!*p) {
7475 if (err)
7476 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7477 return ERR_ALERT | ERR_FATAL;
7478 }
7479
7480 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7481 ignerr = &conf->ca_ignerr;
7482
7483 if (strcmp(p, "all") == 0) {
7484 *ignerr = ~0ULL;
7485 return 0;
7486 }
7487
7488 while (p) {
7489 code = atoi(p);
7490 if ((code <= 0) || (code > 63)) {
7491 if (err)
7492 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7493 args[cur_arg], code, args[cur_arg + 1]);
7494 return ERR_ALERT | ERR_FATAL;
7495 }
7496 *ignerr |= 1ULL << code;
7497 p = strchr(p, ',');
7498 if (p)
7499 p++;
7500 }
7501
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007502 return 0;
7503}
7504
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007505/* parse tls_method_options "no-xxx" and "force-xxx" */
7506static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007507{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007508 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007509 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007510 p = strchr(arg, '-');
7511 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007512 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007513 p++;
7514 if (!strcmp(p, "sslv3"))
7515 v = CONF_SSLV3;
7516 else if (!strcmp(p, "tlsv10"))
7517 v = CONF_TLSV10;
7518 else if (!strcmp(p, "tlsv11"))
7519 v = CONF_TLSV11;
7520 else if (!strcmp(p, "tlsv12"))
7521 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007522 else if (!strcmp(p, "tlsv13"))
7523 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007524 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007525 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007526 if (!strncmp(arg, "no-", 3))
7527 methods->flags |= methodVersions[v].flag;
7528 else if (!strncmp(arg, "force-", 6))
7529 methods->min = methods->max = v;
7530 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007531 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007532 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007533 fail:
7534 if (err)
7535 memprintf(err, "'%s' : option not implemented", arg);
7536 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007537}
7538
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007539static 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 +02007540{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007541 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007542}
7543
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007544static 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 +02007545{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007546 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7547}
7548
7549/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7550static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7551{
7552 uint16_t i, v = 0;
7553 char *argv = args[cur_arg + 1];
7554 if (!*argv) {
7555 if (err)
7556 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7557 return ERR_ALERT | ERR_FATAL;
7558 }
7559 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7560 if (!strcmp(argv, methodVersions[i].name))
7561 v = i;
7562 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007563 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007564 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007565 return ERR_ALERT | ERR_FATAL;
7566 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007567 if (!strcmp("ssl-min-ver", args[cur_arg]))
7568 methods->min = v;
7569 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7570 methods->max = v;
7571 else {
7572 if (err)
7573 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7574 return ERR_ALERT | ERR_FATAL;
7575 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007576 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007577}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007578
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007579static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7580{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007581#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007582 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 +02007583#endif
7584 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7585}
7586
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007587static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7588{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007589 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007590}
7591
7592static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7593{
7594 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7595}
7596
Emeric Brun2d0c4822012-10-02 13:45:20 +02007597/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007598static 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 +02007599{
Emeric Brun89675492012-10-05 13:48:26 +02007600 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007601 return 0;
7602}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007603
Olivier Houchardc2aae742017-09-22 18:26:28 +02007604/* parse the "allow-0rtt" bind keyword */
7605static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7606{
7607 conf->early_data = 1;
7608 return 0;
7609}
7610
7611static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7612{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007613 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007614 return 0;
7615}
7616
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007617/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007618static 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 +02007619{
Bernard Spil13c53f82018-02-15 13:34:58 +01007620#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007621 char *p1, *p2;
7622
7623 if (!*args[cur_arg + 1]) {
7624 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7625 return ERR_ALERT | ERR_FATAL;
7626 }
7627
7628 free(conf->npn_str);
7629
Willy Tarreau3724da12016-02-12 17:11:12 +01007630 /* the NPN string is built as a suite of (<len> <name>)*,
7631 * so we reuse each comma to store the next <len> and need
7632 * one more for the end of the string.
7633 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007634 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007635 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007636 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7637
7638 /* replace commas with the name length */
7639 p1 = conf->npn_str;
7640 p2 = p1 + 1;
7641 while (1) {
7642 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7643 if (!p2)
7644 p2 = p1 + 1 + strlen(p1 + 1);
7645
7646 if (p2 - (p1 + 1) > 255) {
7647 *p2 = '\0';
7648 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7649 return ERR_ALERT | ERR_FATAL;
7650 }
7651
7652 *p1 = p2 - (p1 + 1);
7653 p1 = p2;
7654
7655 if (!*p2)
7656 break;
7657
7658 *(p2++) = '\0';
7659 }
7660 return 0;
7661#else
7662 if (err)
7663 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7664 return ERR_ALERT | ERR_FATAL;
7665#endif
7666}
7667
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007668static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7669{
7670 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7671}
7672
Willy Tarreauab861d32013-04-02 02:30:41 +02007673/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007674static 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 +02007675{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007676#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007677 char *p1, *p2;
7678
7679 if (!*args[cur_arg + 1]) {
7680 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7681 return ERR_ALERT | ERR_FATAL;
7682 }
7683
7684 free(conf->alpn_str);
7685
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007686 /* the ALPN string is built as a suite of (<len> <name>)*,
7687 * so we reuse each comma to store the next <len> and need
7688 * one more for the end of the string.
7689 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007690 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007691 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007692 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7693
7694 /* replace commas with the name length */
7695 p1 = conf->alpn_str;
7696 p2 = p1 + 1;
7697 while (1) {
7698 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7699 if (!p2)
7700 p2 = p1 + 1 + strlen(p1 + 1);
7701
7702 if (p2 - (p1 + 1) > 255) {
7703 *p2 = '\0';
7704 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7705 return ERR_ALERT | ERR_FATAL;
7706 }
7707
7708 *p1 = p2 - (p1 + 1);
7709 p1 = p2;
7710
7711 if (!*p2)
7712 break;
7713
7714 *(p2++) = '\0';
7715 }
7716 return 0;
7717#else
7718 if (err)
7719 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7720 return ERR_ALERT | ERR_FATAL;
7721#endif
7722}
7723
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007724static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7725{
7726 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7727}
7728
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007729/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007730static 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 +02007731{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007732 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007733 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007734
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007735 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7736 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007737#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7738 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7739 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7740#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007741 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007742 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7743 if (!conf->ssl_conf.ssl_methods.min)
7744 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7745 if (!conf->ssl_conf.ssl_methods.max)
7746 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007747
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007748 return 0;
7749}
7750
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007751/* parse the "prefer-client-ciphers" bind keyword */
7752static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7753{
7754 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7755 return 0;
7756}
7757
Christopher Faulet31af49d2015-06-09 17:29:50 +02007758/* parse the "generate-certificates" bind keyword */
7759static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7760{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007761#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007762 conf->generate_certs = 1;
7763#else
7764 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7765 err && *err ? *err : "");
7766#endif
7767 return 0;
7768}
7769
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007770/* parse the "strict-sni" bind keyword */
7771static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7772{
7773 conf->strict_sni = 1;
7774 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007775}
7776
7777/* parse the "tls-ticket-keys" bind keyword */
7778static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7779{
7780#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7781 FILE *f;
7782 int i = 0;
7783 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007784 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007785
7786 if (!*args[cur_arg + 1]) {
7787 if (err)
7788 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7789 return ERR_ALERT | ERR_FATAL;
7790 }
7791
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007792 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007793 if (keys_ref) {
7794 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007795 conf->keys_ref = keys_ref;
7796 return 0;
7797 }
7798
Vincent Bernat02779b62016-04-03 13:48:43 +02007799 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007800 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007801
7802 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7803 if (err)
7804 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7805 return ERR_ALERT | ERR_FATAL;
7806 }
7807
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007808 keys_ref->filename = strdup(args[cur_arg + 1]);
7809
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007810 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7811 int len = strlen(thisline);
7812 /* Strip newline characters from the end */
7813 if(thisline[len - 1] == '\n')
7814 thisline[--len] = 0;
7815
7816 if(thisline[len - 1] == '\r')
7817 thisline[--len] = 0;
7818
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007819 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 +01007820 if (err)
7821 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007822 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007823 return ERR_ALERT | ERR_FATAL;
7824 }
7825 i++;
7826 }
7827
7828 if (i < TLS_TICKETS_NO) {
7829 if (err)
7830 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 +02007831 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007832 return ERR_ALERT | ERR_FATAL;
7833 }
7834
7835 fclose(f);
7836
7837 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007838 i -= 2;
7839 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007840 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007841 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007842 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007843 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007844
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007845 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7846
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007847 return 0;
7848#else
7849 if (err)
7850 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7851 return ERR_ALERT | ERR_FATAL;
7852#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007853}
7854
Emeric Brund94b3fe2012-09-20 18:23:56 +02007855/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007856static 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 +02007857{
7858 if (!*args[cur_arg + 1]) {
7859 if (err)
7860 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7861 return ERR_ALERT | ERR_FATAL;
7862 }
7863
7864 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007865 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007866 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007867 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007868 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007869 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007870 else {
7871 if (err)
7872 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7873 args[cur_arg], args[cur_arg + 1]);
7874 return ERR_ALERT | ERR_FATAL;
7875 }
7876
7877 return 0;
7878}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007879static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7880{
7881 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7882}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007883
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007884/* parse the "no-ca-names" bind keyword */
7885static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7886{
7887 conf->no_ca_names = 1;
7888 return 0;
7889}
7890static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7891{
7892 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7893}
7894
Willy Tarreau92faadf2012-10-10 23:04:25 +02007895/************** "server" keywords ****************/
7896
Olivier Houchardc7566002018-11-20 23:33:50 +01007897/* parse the "npn" bind keyword */
7898static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7899{
7900#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7901 char *p1, *p2;
7902
7903 if (!*args[*cur_arg + 1]) {
7904 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7905 return ERR_ALERT | ERR_FATAL;
7906 }
7907
7908 free(newsrv->ssl_ctx.npn_str);
7909
7910 /* the NPN string is built as a suite of (<len> <name>)*,
7911 * so we reuse each comma to store the next <len> and need
7912 * one more for the end of the string.
7913 */
7914 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7915 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7916 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7917 newsrv->ssl_ctx.npn_len);
7918
7919 /* replace commas with the name length */
7920 p1 = newsrv->ssl_ctx.npn_str;
7921 p2 = p1 + 1;
7922 while (1) {
7923 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7924 newsrv->ssl_ctx.npn_len - (p1 + 1));
7925 if (!p2)
7926 p2 = p1 + 1 + strlen(p1 + 1);
7927
7928 if (p2 - (p1 + 1) > 255) {
7929 *p2 = '\0';
7930 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7931 return ERR_ALERT | ERR_FATAL;
7932 }
7933
7934 *p1 = p2 - (p1 + 1);
7935 p1 = p2;
7936
7937 if (!*p2)
7938 break;
7939
7940 *(p2++) = '\0';
7941 }
7942 return 0;
7943#else
7944 if (err)
7945 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7946 return ERR_ALERT | ERR_FATAL;
7947#endif
7948}
7949
7950/* parse the "alpn" bind keyword */
7951static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7952{
7953#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7954 char *p1, *p2;
7955
7956 if (!*args[*cur_arg + 1]) {
7957 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7958 return ERR_ALERT | ERR_FATAL;
7959 }
7960
7961 free(newsrv->ssl_ctx.alpn_str);
7962
7963 /* the ALPN string is built as a suite of (<len> <name>)*,
7964 * so we reuse each comma to store the next <len> and need
7965 * one more for the end of the string.
7966 */
7967 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7968 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7969 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7970 newsrv->ssl_ctx.alpn_len);
7971
7972 /* replace commas with the name length */
7973 p1 = newsrv->ssl_ctx.alpn_str;
7974 p2 = p1 + 1;
7975 while (1) {
7976 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7977 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7978 if (!p2)
7979 p2 = p1 + 1 + strlen(p1 + 1);
7980
7981 if (p2 - (p1 + 1) > 255) {
7982 *p2 = '\0';
7983 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7984 return ERR_ALERT | ERR_FATAL;
7985 }
7986
7987 *p1 = p2 - (p1 + 1);
7988 p1 = p2;
7989
7990 if (!*p2)
7991 break;
7992
7993 *(p2++) = '\0';
7994 }
7995 return 0;
7996#else
7997 if (err)
7998 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
7999 return ERR_ALERT | ERR_FATAL;
8000#endif
8001}
8002
Emeric Brunef42d922012-10-11 16:11:36 +02008003/* parse the "ca-file" server keyword */
8004static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8005{
8006 if (!*args[*cur_arg + 1]) {
8007 if (err)
8008 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8009 return ERR_ALERT | ERR_FATAL;
8010 }
8011
Willy Tarreauef934602016-12-22 23:12:01 +01008012 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8013 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008014 else
8015 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8016
8017 return 0;
8018}
8019
Olivier Houchard9130a962017-10-17 17:33:43 +02008020/* parse the "check-sni" server keyword */
8021static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8022{
8023 if (!*args[*cur_arg + 1]) {
8024 if (err)
8025 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8026 return ERR_ALERT | ERR_FATAL;
8027 }
8028
8029 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8030 if (!newsrv->check.sni) {
8031 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8032 return ERR_ALERT | ERR_FATAL;
8033 }
8034 return 0;
8035
8036}
8037
Willy Tarreau92faadf2012-10-10 23:04:25 +02008038/* parse the "check-ssl" server keyword */
8039static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8040{
8041 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008042 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8043 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008044#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8045 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8046 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8047#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008048 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008049 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8050 if (!newsrv->ssl_ctx.methods.min)
8051 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8052 if (!newsrv->ssl_ctx.methods.max)
8053 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8054
Willy Tarreau92faadf2012-10-10 23:04:25 +02008055 return 0;
8056}
8057
8058/* parse the "ciphers" server keyword */
8059static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8060{
8061 if (!*args[*cur_arg + 1]) {
8062 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8063 return ERR_ALERT | ERR_FATAL;
8064 }
8065
8066 free(newsrv->ssl_ctx.ciphers);
8067 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8068 return 0;
8069}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008070
8071#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8072/* parse the "ciphersuites" server keyword */
8073static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8074{
8075 if (!*args[*cur_arg + 1]) {
8076 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8077 return ERR_ALERT | ERR_FATAL;
8078 }
8079
8080 free(newsrv->ssl_ctx.ciphersuites);
8081 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8082 return 0;
8083}
8084#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008085
Emeric Brunef42d922012-10-11 16:11:36 +02008086/* parse the "crl-file" server keyword */
8087static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8088{
8089#ifndef X509_V_FLAG_CRL_CHECK
8090 if (err)
8091 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8092 return ERR_ALERT | ERR_FATAL;
8093#else
8094 if (!*args[*cur_arg + 1]) {
8095 if (err)
8096 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8097 return ERR_ALERT | ERR_FATAL;
8098 }
8099
Willy Tarreauef934602016-12-22 23:12:01 +01008100 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8101 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008102 else
8103 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8104
8105 return 0;
8106#endif
8107}
8108
Emeric Bruna7aa3092012-10-26 12:58:00 +02008109/* parse the "crt" server keyword */
8110static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8111{
8112 if (!*args[*cur_arg + 1]) {
8113 if (err)
8114 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8115 return ERR_ALERT | ERR_FATAL;
8116 }
8117
Willy Tarreauef934602016-12-22 23:12:01 +01008118 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008119 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008120 else
8121 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8122
8123 return 0;
8124}
Emeric Brunef42d922012-10-11 16:11:36 +02008125
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008126/* parse the "no-check-ssl" server keyword */
8127static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8128{
8129 newsrv->check.use_ssl = 0;
8130 free(newsrv->ssl_ctx.ciphers);
8131 newsrv->ssl_ctx.ciphers = NULL;
8132 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8133 return 0;
8134}
8135
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008136/* parse the "no-send-proxy-v2-ssl" server keyword */
8137static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8138{
8139 newsrv->pp_opts &= ~SRV_PP_V2;
8140 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8141 return 0;
8142}
8143
8144/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8145static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8146{
8147 newsrv->pp_opts &= ~SRV_PP_V2;
8148 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8149 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8150 return 0;
8151}
8152
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008153/* parse the "no-ssl" server keyword */
8154static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8155{
8156 newsrv->use_ssl = 0;
8157 free(newsrv->ssl_ctx.ciphers);
8158 newsrv->ssl_ctx.ciphers = NULL;
8159 return 0;
8160}
8161
Olivier Houchard522eea72017-11-03 16:27:47 +01008162/* parse the "allow-0rtt" server keyword */
8163static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8164{
8165 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8166 return 0;
8167}
8168
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008169/* parse the "no-ssl-reuse" server keyword */
8170static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8171{
8172 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8173 return 0;
8174}
8175
Emeric Brunf9c5c472012-10-11 15:28:34 +02008176/* parse the "no-tls-tickets" server keyword */
8177static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8178{
8179 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8180 return 0;
8181}
David Safb76832014-05-08 23:42:08 -04008182/* parse the "send-proxy-v2-ssl" server keyword */
8183static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8184{
8185 newsrv->pp_opts |= SRV_PP_V2;
8186 newsrv->pp_opts |= SRV_PP_V2_SSL;
8187 return 0;
8188}
8189
8190/* parse the "send-proxy-v2-ssl-cn" server keyword */
8191static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8192{
8193 newsrv->pp_opts |= SRV_PP_V2;
8194 newsrv->pp_opts |= SRV_PP_V2_SSL;
8195 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8196 return 0;
8197}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008198
Willy Tarreau732eac42015-07-09 11:40:25 +02008199/* parse the "sni" server keyword */
8200static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8201{
8202#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8203 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8204 return ERR_ALERT | ERR_FATAL;
8205#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008206 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008207
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008208 arg = args[*cur_arg + 1];
8209 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008210 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8211 return ERR_ALERT | ERR_FATAL;
8212 }
8213
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008214 free(newsrv->sni_expr);
8215 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008216
Willy Tarreau732eac42015-07-09 11:40:25 +02008217 return 0;
8218#endif
8219}
8220
Willy Tarreau92faadf2012-10-10 23:04:25 +02008221/* parse the "ssl" server keyword */
8222static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8223{
8224 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008225 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8226 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008227#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8228 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8229 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8230#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008231 return 0;
8232}
8233
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008234/* parse the "ssl-reuse" server keyword */
8235static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8236{
8237 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8238 return 0;
8239}
8240
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008241/* parse the "tls-tickets" server keyword */
8242static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8243{
8244 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8245 return 0;
8246}
8247
Emeric Brunef42d922012-10-11 16:11:36 +02008248/* parse the "verify" server keyword */
8249static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8250{
8251 if (!*args[*cur_arg + 1]) {
8252 if (err)
8253 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8254 return ERR_ALERT | ERR_FATAL;
8255 }
8256
8257 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008258 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008259 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008260 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008261 else {
8262 if (err)
8263 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8264 args[*cur_arg], args[*cur_arg + 1]);
8265 return ERR_ALERT | ERR_FATAL;
8266 }
8267
Evan Broderbe554312013-06-27 00:05:25 -07008268 return 0;
8269}
8270
8271/* parse the "verifyhost" server keyword */
8272static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8273{
8274 if (!*args[*cur_arg + 1]) {
8275 if (err)
8276 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8277 return ERR_ALERT | ERR_FATAL;
8278 }
8279
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008280 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008281 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8282
Emeric Brunef42d922012-10-11 16:11:36 +02008283 return 0;
8284}
8285
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008286/* parse the "ssl-default-bind-options" keyword in global section */
8287static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8288 struct proxy *defpx, const char *file, int line,
8289 char **err) {
8290 int i = 1;
8291
8292 if (*(args[i]) == 0) {
8293 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8294 return -1;
8295 }
8296 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008297 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008298 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008299 else if (!strcmp(args[i], "prefer-client-ciphers"))
8300 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008301 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8302 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8303 i++;
8304 else {
8305 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8306 return -1;
8307 }
8308 }
8309 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008310 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8311 return -1;
8312 }
8313 i++;
8314 }
8315 return 0;
8316}
8317
8318/* parse the "ssl-default-server-options" keyword in global section */
8319static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8320 struct proxy *defpx, const char *file, int line,
8321 char **err) {
8322 int i = 1;
8323
8324 if (*(args[i]) == 0) {
8325 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8326 return -1;
8327 }
8328 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008329 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008330 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008331 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8332 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8333 i++;
8334 else {
8335 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8336 return -1;
8337 }
8338 }
8339 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008340 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8341 return -1;
8342 }
8343 i++;
8344 }
8345 return 0;
8346}
8347
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008348/* parse the "ca-base" / "crt-base" keywords in global section.
8349 * Returns <0 on alert, >0 on warning, 0 on success.
8350 */
8351static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8352 struct proxy *defpx, const char *file, int line,
8353 char **err)
8354{
8355 char **target;
8356
Willy Tarreauef934602016-12-22 23:12:01 +01008357 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008358
8359 if (too_many_args(1, args, err, NULL))
8360 return -1;
8361
8362 if (*target) {
8363 memprintf(err, "'%s' already specified.", args[0]);
8364 return -1;
8365 }
8366
8367 if (*(args[1]) == 0) {
8368 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8369 return -1;
8370 }
8371 *target = strdup(args[1]);
8372 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008373}
8374
8375/* parse the "ssl-mode-async" keyword in global section.
8376 * Returns <0 on alert, >0 on warning, 0 on success.
8377 */
8378static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8379 struct proxy *defpx, const char *file, int line,
8380 char **err)
8381{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008382#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008383 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008384 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008385 return 0;
8386#else
8387 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8388 return -1;
8389#endif
8390}
8391
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008392#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008393static int ssl_check_async_engine_count(void) {
8394 int err_code = 0;
8395
Emeric Brun3854e012017-05-17 20:42:48 +02008396 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008397 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008398 err_code = ERR_ABORT;
8399 }
8400 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008401}
8402
Grant Zhang872f9c22017-01-21 01:10:18 +00008403/* parse the "ssl-engine" keyword in global section.
8404 * Returns <0 on alert, >0 on warning, 0 on success.
8405 */
8406static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8407 struct proxy *defpx, const char *file, int line,
8408 char **err)
8409{
8410 char *algo;
8411 int ret = -1;
8412
8413 if (*(args[1]) == 0) {
8414 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8415 return ret;
8416 }
8417
8418 if (*(args[2]) == 0) {
8419 /* if no list of algorithms is given, it defaults to ALL */
8420 algo = strdup("ALL");
8421 goto add_engine;
8422 }
8423
8424 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8425 if (strcmp(args[2], "algo") != 0) {
8426 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8427 return ret;
8428 }
8429
8430 if (*(args[3]) == 0) {
8431 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8432 return ret;
8433 }
8434 algo = strdup(args[3]);
8435
8436add_engine:
8437 if (ssl_init_single_engine(args[1], algo)==0) {
8438 openssl_engines_initialized++;
8439 ret = 0;
8440 }
8441 free(algo);
8442 return ret;
8443}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008444#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008445
Willy Tarreauf22e9682016-12-21 23:23:19 +01008446/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8447 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8448 */
8449static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8450 struct proxy *defpx, const char *file, int line,
8451 char **err)
8452{
8453 char **target;
8454
Willy Tarreauef934602016-12-22 23:12:01 +01008455 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008456
8457 if (too_many_args(1, args, err, NULL))
8458 return -1;
8459
8460 if (*(args[1]) == 0) {
8461 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8462 return -1;
8463 }
8464
8465 free(*target);
8466 *target = strdup(args[1]);
8467 return 0;
8468}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008469
8470#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8471/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8472 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8473 */
8474static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8475 struct proxy *defpx, const char *file, int line,
8476 char **err)
8477{
8478 char **target;
8479
8480 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8481
8482 if (too_many_args(1, args, err, NULL))
8483 return -1;
8484
8485 if (*(args[1]) == 0) {
8486 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8487 return -1;
8488 }
8489
8490 free(*target);
8491 *target = strdup(args[1]);
8492 return 0;
8493}
8494#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008495
Willy Tarreau9ceda382016-12-21 23:13:03 +01008496/* parse various global tune.ssl settings consisting in positive integers.
8497 * Returns <0 on alert, >0 on warning, 0 on success.
8498 */
8499static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8500 struct proxy *defpx, const char *file, int line,
8501 char **err)
8502{
8503 int *target;
8504
8505 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8506 target = &global.tune.sslcachesize;
8507 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008508 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008509 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008510 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008511 else if (strcmp(args[0], "maxsslconn") == 0)
8512 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008513 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8514 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008515 else {
8516 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8517 return -1;
8518 }
8519
8520 if (too_many_args(1, args, err, NULL))
8521 return -1;
8522
8523 if (*(args[1]) == 0) {
8524 memprintf(err, "'%s' expects an integer argument.", args[0]);
8525 return -1;
8526 }
8527
8528 *target = atoi(args[1]);
8529 if (*target < 0) {
8530 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8531 return -1;
8532 }
8533 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008534}
8535
8536static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8537 struct proxy *defpx, const char *file, int line,
8538 char **err)
8539{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008540 int ret;
8541
8542 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8543 if (ret != 0)
8544 return ret;
8545
Willy Tarreaubafbe012017-11-24 17:34:44 +01008546 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008547 memprintf(err, "'%s' is already configured.", args[0]);
8548 return -1;
8549 }
8550
Willy Tarreaubafbe012017-11-24 17:34:44 +01008551 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8552 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008553 memprintf(err, "Out of memory error.");
8554 return -1;
8555 }
8556 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008557}
8558
8559/* parse "ssl.force-private-cache".
8560 * Returns <0 on alert, >0 on warning, 0 on success.
8561 */
8562static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8563 struct proxy *defpx, const char *file, int line,
8564 char **err)
8565{
8566 if (too_many_args(0, args, err, NULL))
8567 return -1;
8568
Willy Tarreauef934602016-12-22 23:12:01 +01008569 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008570 return 0;
8571}
8572
8573/* parse "ssl.lifetime".
8574 * Returns <0 on alert, >0 on warning, 0 on success.
8575 */
8576static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8577 struct proxy *defpx, const char *file, int line,
8578 char **err)
8579{
8580 const char *res;
8581
8582 if (too_many_args(1, args, err, NULL))
8583 return -1;
8584
8585 if (*(args[1]) == 0) {
8586 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8587 return -1;
8588 }
8589
Willy Tarreauef934602016-12-22 23:12:01 +01008590 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008591 if (res) {
8592 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8593 return -1;
8594 }
8595 return 0;
8596}
8597
8598#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008599/* parse "ssl-dh-param-file".
8600 * Returns <0 on alert, >0 on warning, 0 on success.
8601 */
8602static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8603 struct proxy *defpx, const char *file, int line,
8604 char **err)
8605{
8606 if (too_many_args(1, args, err, NULL))
8607 return -1;
8608
8609 if (*(args[1]) == 0) {
8610 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8611 return -1;
8612 }
8613
8614 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8615 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8616 return -1;
8617 }
8618 return 0;
8619}
8620
Willy Tarreau9ceda382016-12-21 23:13:03 +01008621/* parse "ssl.default-dh-param".
8622 * Returns <0 on alert, >0 on warning, 0 on success.
8623 */
8624static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8625 struct proxy *defpx, const char *file, int line,
8626 char **err)
8627{
8628 if (too_many_args(1, args, err, NULL))
8629 return -1;
8630
8631 if (*(args[1]) == 0) {
8632 memprintf(err, "'%s' expects an integer argument.", args[0]);
8633 return -1;
8634 }
8635
Willy Tarreauef934602016-12-22 23:12:01 +01008636 global_ssl.default_dh_param = atoi(args[1]);
8637 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008638 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8639 return -1;
8640 }
8641 return 0;
8642}
8643#endif
8644
8645
William Lallemand32af2032016-10-29 18:09:35 +02008646/* This function is used with TLS ticket keys management. It permits to browse
8647 * each reference. The variable <getnext> must contain the current node,
8648 * <end> point to the root node.
8649 */
8650#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8651static inline
8652struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8653{
8654 struct tls_keys_ref *ref = getnext;
8655
8656 while (1) {
8657
8658 /* Get next list entry. */
8659 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8660
8661 /* If the entry is the last of the list, return NULL. */
8662 if (&ref->list == end)
8663 return NULL;
8664
8665 return ref;
8666 }
8667}
8668
8669static inline
8670struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8671{
8672 int id;
8673 char *error;
8674
8675 /* If the reference starts by a '#', this is numeric id. */
8676 if (reference[0] == '#') {
8677 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8678 id = strtol(reference + 1, &error, 10);
8679 if (*error != '\0')
8680 return NULL;
8681
8682 /* Perform the unique id lookup. */
8683 return tlskeys_ref_lookupid(id);
8684 }
8685
8686 /* Perform the string lookup. */
8687 return tlskeys_ref_lookup(reference);
8688}
8689#endif
8690
8691
8692#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8693
8694static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8695
8696static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8697 return cli_io_handler_tlskeys_files(appctx);
8698}
8699
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008700/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8701 * (next index to be dumped), and cli.p0 (next key reference).
8702 */
William Lallemand32af2032016-10-29 18:09:35 +02008703static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8704
8705 struct stream_interface *si = appctx->owner;
8706
8707 switch (appctx->st2) {
8708 case STAT_ST_INIT:
8709 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008710 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008711 * later and restart at the state "STAT_ST_INIT".
8712 */
8713 chunk_reset(&trash);
8714
8715 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8716 chunk_appendf(&trash, "# id secret\n");
8717 else
8718 chunk_appendf(&trash, "# id (file)\n");
8719
Willy Tarreau06d80a92017-10-19 14:32:15 +02008720 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008721 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008722 return 0;
8723 }
8724
William Lallemand32af2032016-10-29 18:09:35 +02008725 /* Now, we start the browsing of the references lists.
8726 * Note that the following call to LIST_ELEM return bad pointer. The only
8727 * available field of this pointer is <list>. It is used with the function
8728 * tlskeys_list_get_next() for retruning the first available entry
8729 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008730 if (appctx->ctx.cli.p0 == NULL) {
8731 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8732 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008733 }
8734
8735 appctx->st2 = STAT_ST_LIST;
8736 /* fall through */
8737
8738 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008739 while (appctx->ctx.cli.p0) {
8740 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008741
8742 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008743 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008744 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008745
8746 if (appctx->ctx.cli.i1 == 0)
8747 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8748
William Lallemand32af2032016-10-29 18:09:35 +02008749 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008750 int head;
8751
8752 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8753 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008754 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008755 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008756
8757 chunk_reset(t2);
8758 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008759 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8760 sizeof(struct tls_sess_key),
8761 t2->area, t2->size);
8762 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8763 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008764
Willy Tarreau06d80a92017-10-19 14:32:15 +02008765 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008766 /* let's try again later from this stream. We add ourselves into
8767 * this stream's users so that it can remove us upon termination.
8768 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008769 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008770 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008771 return 0;
8772 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008773 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008774 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008775 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008776 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008777 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008778 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008779 /* let's try again later from this stream. We add ourselves into
8780 * this stream's users so that it can remove us upon termination.
8781 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008782 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008783 return 0;
8784 }
8785
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008786 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008787 break;
8788
8789 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008790 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008791 }
8792
8793 appctx->st2 = STAT_ST_FIN;
8794 /* fall through */
8795
8796 default:
8797 appctx->st2 = STAT_ST_FIN;
8798 return 1;
8799 }
8800 return 0;
8801}
8802
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008803/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008804static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008805{
William Lallemand32af2032016-10-29 18:09:35 +02008806 /* no parameter, shows only file list */
8807 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008808 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008809 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008810 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008811 }
8812
8813 if (args[2][0] == '*') {
8814 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008815 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008816 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008817 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8818 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008819 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008820 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008821 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008822 return 1;
8823 }
8824 }
William Lallemand32af2032016-10-29 18:09:35 +02008825 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008826 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008827}
8828
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008829static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008830{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008831 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008832 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008833
William Lallemand32af2032016-10-29 18:09:35 +02008834 /* Expect two parameters: the filename and the new new TLS key in encoding */
8835 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008836 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008837 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 +01008838 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008839 return 1;
8840 }
8841
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008842 ref = tlskeys_ref_lookup_ref(args[3]);
8843 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008844 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008845 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008846 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008847 return 1;
8848 }
8849
Willy Tarreau1c913e42018-08-22 05:26:57 +02008850 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8851 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008852 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008853 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008854 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008855 return 1;
8856 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008857 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008858 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008859 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008860 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008861 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008862 return 1;
8863
8864}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008865#endif
William Lallemand32af2032016-10-29 18:09:35 +02008866
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008867static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008868{
8869#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8870 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008871 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008872
8873 if (!payload)
8874 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008875
8876 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008877 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008878 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008879 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008880 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008881 return 1;
8882 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008883
8884 /* remove \r and \n from the payload */
8885 for (i = 0, j = 0; payload[i]; i++) {
8886 if (payload[i] == '\r' || payload[i] == '\n')
8887 continue;
8888 payload[j++] = payload[i];
8889 }
8890 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008891
Willy Tarreau1c913e42018-08-22 05:26:57 +02008892 ret = base64dec(payload, j, trash.area, trash.size);
8893 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008894 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008895 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008896 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008897 return 1;
8898 }
8899
Willy Tarreau1c913e42018-08-22 05:26:57 +02008900 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008901 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8902 if (err) {
8903 memprintf(&err, "%s.\n", err);
8904 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008905 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008906 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008907 else {
8908 appctx->ctx.cli.severity = LOG_ERR;
8909 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8910 appctx->st0 = CLI_ST_PRINT;
8911 }
William Lallemand32af2032016-10-29 18:09:35 +02008912 return 1;
8913 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008914 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008915 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008916 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008917 return 1;
8918#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008919 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008920 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 +01008921 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008922 return 1;
8923#endif
8924
8925}
8926
8927/* register cli keywords */
8928static struct cli_kw_list cli_kws = {{ },{
8929#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8930 { { "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 +02008931 { { "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 +02008932#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008933 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008934 { { NULL }, NULL, NULL, NULL }
8935}};
8936
Willy Tarreau0108d902018-11-25 19:14:37 +01008937INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008938
Willy Tarreau7875d092012-09-10 08:20:03 +02008939/* Note: must not be declared <const> as its list will be overwritten.
8940 * Please take care of keeping this list alphabetically sorted.
8941 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008942static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008943 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008944 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008945#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01008946 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008947#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008948 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008949#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8950 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8951#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008952 { "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 +02008953 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008954 { "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 +02008955 { "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 -04008956#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008957 { "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 -04008958#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008959#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8960 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8961#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008962 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8963 { "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 +01008964 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008965 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008966 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8967 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8968 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8969 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8970 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8971 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8972 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8973 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008974 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008975 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8976 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008977 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008978 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8979 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8980 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8981 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8982 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8983 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8984 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008985 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008986 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008987 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008988 { "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 +01008989 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008990 { "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 +02008991 { "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 +01008992 { "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 +02008993 { "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 +01008994#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008995 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008996#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008997#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008998 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008999#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009000 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009001#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009002 { "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 -04009003#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009004 { "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 -04009005#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009006 { "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 -04009007#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009008#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9009 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9010#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009011#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009012 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009013#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009014 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9015 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9016 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9017 { "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 +02009018 { NULL, NULL, 0, 0, 0 },
9019}};
9020
Willy Tarreau0108d902018-11-25 19:14:37 +01009021INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9022
Willy Tarreau7875d092012-09-10 08:20:03 +02009023/* Note: must not be declared <const> as its list will be overwritten.
9024 * Please take care of keeping this list alphabetically sorted.
9025 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009026static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009027 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9028 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009029 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009030}};
9031
Willy Tarreau0108d902018-11-25 19:14:37 +01009032INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9033
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009034/* Note: must not be declared <const> as its list will be overwritten.
9035 * Please take care of keeping this list alphabetically sorted, doing so helps
9036 * all code contributors.
9037 * Optional keywords are also declared with a NULL ->parse() function so that
9038 * the config parser can report an appropriate error when a known keyword was
9039 * not enabled.
9040 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009041static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009042 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009043 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9044 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9045 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009046#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9047 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9048#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009049 { "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 +01009050 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009051 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009052 { "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 +01009053 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009054 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9055 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009056 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9057 { NULL, NULL, 0 },
9058};
9059
Willy Tarreau0108d902018-11-25 19:14:37 +01009060/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9061
Willy Tarreau51fb7652012-09-18 18:24:39 +02009062static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009063 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009064 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9065 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9066 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9067 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9068 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9069 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009070#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9071 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9072#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009073 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9074 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9075 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9076 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9077 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9078 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9079 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9080 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9081 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9082 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009083 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009084 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009085 { "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 +02009086 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9087 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9088 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9089 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009090 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009091 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9092 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009093 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9094 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009095 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9096 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9097 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9098 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9099 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009100 { NULL, NULL, 0 },
9101}};
Emeric Brun46591952012-05-18 15:47:34 +02009102
Willy Tarreau0108d902018-11-25 19:14:37 +01009103INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9104
Willy Tarreau92faadf2012-10-10 23:04:25 +02009105/* Note: must not be declared <const> as its list will be overwritten.
9106 * Please take care of keeping this list alphabetically sorted, doing so helps
9107 * all code contributors.
9108 * Optional keywords are also declared with a NULL ->parse() function so that
9109 * the config parser can report an appropriate error when a known keyword was
9110 * not enabled.
9111 */
9112static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009113 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009114 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009115 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009116 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009117 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9118 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009119#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9120 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9121#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009122 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9123 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9124 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9125 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9126 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9127 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9128 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9129 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9130 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9131 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9132 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9133 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9134 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9135 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9136 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9137 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9138 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9139 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009140 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009141 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9142 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9143 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9144 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9145 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9146 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9147 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9148 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9149 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9150 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009151 { NULL, NULL, 0, 0 },
9152}};
9153
Willy Tarreau0108d902018-11-25 19:14:37 +01009154INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9155
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009156static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009157 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9158 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009159 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009160 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9161 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009162#ifndef OPENSSL_NO_DH
9163 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9164#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009165 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009166#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009167 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009168#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009169 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9170#ifndef OPENSSL_NO_DH
9171 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9172#endif
9173 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9174 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9175 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9176 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009177 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009178 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9179 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009180#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9181 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9182 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9183#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009184 { 0, NULL, NULL },
9185}};
9186
Willy Tarreau0108d902018-11-25 19:14:37 +01009187INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9188
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009189/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009190static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009191 .snd_buf = ssl_sock_from_buf,
9192 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009193 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009194 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009195 .rcv_pipe = NULL,
9196 .snd_pipe = NULL,
9197 .shutr = NULL,
9198 .shutw = ssl_sock_shutw,
9199 .close = ssl_sock_close,
9200 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009201 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009202 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009203 .prepare_srv = ssl_sock_prepare_srv_ctx,
9204 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009205 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009206 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009207};
9208
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009209enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9210 struct session *sess, struct stream *s, int flags)
9211{
9212 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009213 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009214
9215 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009216 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009217
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009218 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009219 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009220 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009221 s->req.flags |= CF_READ_NULL;
9222 return ACT_RET_YIELD;
9223 }
9224 }
9225 return (ACT_RET_CONT);
9226}
9227
9228static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9229{
9230 rule->action_ptr = ssl_action_wait_for_hs;
9231
9232 return ACT_RET_PRS_OK;
9233}
9234
9235static struct action_kw_list http_req_actions = {ILH, {
9236 { "wait-for-handshake", ssl_parse_wait_for_hs },
9237 { /* END */ }
9238}};
9239
Willy Tarreau0108d902018-11-25 19:14:37 +01009240INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9241
Daniel Jakots54ffb912015-11-06 20:02:41 +01009242#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009243
9244static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9245{
9246 if (ptr) {
9247 chunk_destroy(ptr);
9248 free(ptr);
9249 }
9250}
9251
9252#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009253static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9254{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009255 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009256}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009257
Emeric Brun46591952012-05-18 15:47:34 +02009258__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009259static void __ssl_sock_init(void)
9260{
Emeric Brun46591952012-05-18 15:47:34 +02009261 STACK_OF(SSL_COMP)* cm;
9262
Willy Tarreauef934602016-12-22 23:12:01 +01009263 if (global_ssl.listen_default_ciphers)
9264 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9265 if (global_ssl.connect_default_ciphers)
9266 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009267#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9268 if (global_ssl.listen_default_ciphersuites)
9269 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9270 if (global_ssl.connect_default_ciphersuites)
9271 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9272#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009273
Willy Tarreau13e14102016-12-22 20:25:26 +01009274 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009275 SSL_library_init();
9276 cm = SSL_COMP_get_compression_methods();
9277 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009278#ifdef USE_THREAD
9279 ssl_locking_init();
9280#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009281#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009282 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9283#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009284 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009285 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 +01009286 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009287#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009288 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009289 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009290#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009291#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9292 hap_register_post_check(tlskeys_finalize_config);
9293#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009294
9295 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9296 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9297
9298#ifndef OPENSSL_NO_DH
9299 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9300 hap_register_post_deinit(ssl_free_dh);
9301#endif
9302#ifndef OPENSSL_NO_ENGINE
9303 hap_register_post_deinit(ssl_free_engines);
9304#endif
9305 /* Load SSL string for the verbose & debug mode. */
9306 ERR_load_SSL_strings();
9307}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009308
Willy Tarreau80713382018-11-26 10:19:54 +01009309/* Compute and register the version string */
9310static void ssl_register_build_options()
9311{
9312 char *ptr = NULL;
9313 int i;
9314
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009315 memprintf(&ptr, "Built with OpenSSL version : "
9316#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009317 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009318#else /* OPENSSL_IS_BORINGSSL */
9319 OPENSSL_VERSION_TEXT
9320 "\nRunning on OpenSSL version : %s%s",
9321 SSLeay_version(SSLEAY_VERSION),
9322 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9323#endif
9324 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9325#if OPENSSL_VERSION_NUMBER < 0x00907000L
9326 "no (library version too old)"
9327#elif defined(OPENSSL_NO_TLSEXT)
9328 "no (disabled via OPENSSL_NO_TLSEXT)"
9329#else
9330 "yes"
9331#endif
9332 "", ptr);
9333
9334 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9335#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9336 "yes"
9337#else
9338#ifdef OPENSSL_NO_TLSEXT
9339 "no (because of OPENSSL_NO_TLSEXT)"
9340#else
9341 "no (version might be too old, 0.9.8f min needed)"
9342#endif
9343#endif
9344 "", ptr);
9345
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009346 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9347 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9348 if (methodVersions[i].option)
9349 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009350
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009351 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009352}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009353
Willy Tarreau80713382018-11-26 10:19:54 +01009354INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009355
Emeric Brun46591952012-05-18 15:47:34 +02009356
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009357#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009358void ssl_free_engines(void) {
9359 struct ssl_engine_list *wl, *wlb;
9360 /* free up engine list */
9361 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9362 ENGINE_finish(wl->e);
9363 ENGINE_free(wl->e);
9364 LIST_DEL(&wl->list);
9365 free(wl);
9366 }
9367}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009368#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009369
Remi Gacogned3a23c32015-05-28 16:39:47 +02009370#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009371void ssl_free_dh(void) {
9372 if (local_dh_1024) {
9373 DH_free(local_dh_1024);
9374 local_dh_1024 = NULL;
9375 }
9376 if (local_dh_2048) {
9377 DH_free(local_dh_2048);
9378 local_dh_2048 = NULL;
9379 }
9380 if (local_dh_4096) {
9381 DH_free(local_dh_4096);
9382 local_dh_4096 = NULL;
9383 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009384 if (global_dh) {
9385 DH_free(global_dh);
9386 global_dh = NULL;
9387 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009388}
9389#endif
9390
9391__attribute__((destructor))
9392static void __ssl_sock_deinit(void)
9393{
9394#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009395 if (ssl_ctx_lru_tree) {
9396 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009397 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009398 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009399#endif
9400
9401 ERR_remove_state(0);
9402 ERR_free_strings();
9403
9404 EVP_cleanup();
9405
9406#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9407 CRYPTO_cleanup_all_ex_data();
9408#endif
9409}
9410
9411
Emeric Brun46591952012-05-18 15:47:34 +02009412/*
9413 * Local variables:
9414 * c-indent-level: 8
9415 * c-basic-offset: 8
9416 * End:
9417 */