blob: 174ed1f955679f7509247fae1d015098c642a757 [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;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100325__decl_hathreads(static HA_RWLOCK_T 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
1564 * 28 bytes for unix payload, and them 1 byte for the session id. So
1565 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1566 */
1567 msg += 1 + 1 + 4 + 28 + 1;
1568 if (msg > end)
1569 return;
1570
1571 /* Next two bytes are the ciphersuite length. */
1572 if (msg + 2 > end)
1573 return;
1574 rec_len = (msg[0] << 8) + msg[1];
1575 msg += 2;
1576 if (msg + rec_len > end || msg + rec_len < msg)
1577 return;
1578
Willy Tarreaubafbe012017-11-24 17:34:44 +01001579 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001580 if (!capture)
1581 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001582 /* Compute the xxh64 of the ciphersuite. */
1583 capture->xxh64 = XXH64(msg, rec_len, 0);
1584
1585 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001586 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1587 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001588 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001589
1590 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001591}
1592
Emeric Brun29f037d2014-04-25 19:05:36 +02001593/* Callback is called for ssl protocol analyse */
1594void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1595{
Emeric Brun29f037d2014-04-25 19:05:36 +02001596#ifdef TLS1_RT_HEARTBEAT
1597 /* test heartbeat received (write_p is set to 0
1598 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001599 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001600 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001601 const unsigned char *p = buf;
1602 unsigned int payload;
1603
Emeric Brun29f037d2014-04-25 19:05:36 +02001604 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001605
1606 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1607 if (*p != TLS1_HB_REQUEST)
1608 return;
1609
Willy Tarreauaeed6722014-04-25 23:59:58 +02001610 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001611 goto kill_it;
1612
1613 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001614 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001615 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001616 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001617 /* We have a clear heartbleed attack (CVE-2014-0160), the
1618 * advertised payload is larger than the advertised packet
1619 * length, so we have garbage in the buffer between the
1620 * payload and the end of the buffer (p+len). We can't know
1621 * if the SSL stack is patched, and we don't know if we can
1622 * safely wipe out the area between p+3+len and payload.
1623 * So instead, we prevent the response from being sent by
1624 * setting the max_send_fragment to 0 and we report an SSL
1625 * error, which will kill this connection. It will be reported
1626 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001627 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1628 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001629 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001630 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1631 return;
1632 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001633#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001634 if (global_ssl.capture_cipherlist > 0)
1635 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001636}
1637
Bernard Spil13c53f82018-02-15 13:34:58 +01001638#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001639static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1640 const unsigned char *in, unsigned int inlen,
1641 void *arg)
1642{
1643 struct server *srv = arg;
1644
1645 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1646 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1647 return SSL_TLSEXT_ERR_OK;
1648 return SSL_TLSEXT_ERR_NOACK;
1649}
1650#endif
1651
1652#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001653/* This callback is used so that the server advertises the list of
1654 * negociable protocols for NPN.
1655 */
1656static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1657 unsigned int *len, void *arg)
1658{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001659 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001660
1661 *data = (const unsigned char *)conf->npn_str;
1662 *len = conf->npn_len;
1663 return SSL_TLSEXT_ERR_OK;
1664}
1665#endif
1666
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001667#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001668/* This callback is used so that the server advertises the list of
1669 * negociable protocols for ALPN.
1670 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001671static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1672 unsigned char *outlen,
1673 const unsigned char *server,
1674 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001675{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001676 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001677
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001678 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1679 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1680 return SSL_TLSEXT_ERR_NOACK;
1681 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001682 return SSL_TLSEXT_ERR_OK;
1683}
1684#endif
1685
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001686#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001687#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001688
Christopher Faulet30548802015-06-11 13:39:32 +02001689/* Create a X509 certificate with the specified servername and serial. This
1690 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001691static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001692ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001693{
Christopher Faulet7969a332015-10-09 11:15:03 +02001694 X509 *cacert = bind_conf->ca_sign_cert;
1695 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001696 SSL_CTX *ssl_ctx = NULL;
1697 X509 *newcrt = NULL;
1698 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001699 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001700 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001701 X509_NAME *name;
1702 const EVP_MD *digest;
1703 X509V3_CTX ctx;
1704 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001705 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001706
Christopher Faulet48a83322017-07-28 16:56:09 +02001707 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001708#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1709 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1710#else
1711 tmp_ssl = SSL_new(bind_conf->default_ctx);
1712 if (tmp_ssl)
1713 pkey = SSL_get_privatekey(tmp_ssl);
1714#endif
1715 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001716 goto mkcert_error;
1717
1718 /* Create the certificate */
1719 if (!(newcrt = X509_new()))
1720 goto mkcert_error;
1721
1722 /* Set version number for the certificate (X509v3) and the serial
1723 * number */
1724 if (X509_set_version(newcrt, 2L) != 1)
1725 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001726 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001727
1728 /* Set duration for the certificate */
1729 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1730 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1731 goto mkcert_error;
1732
1733 /* set public key in the certificate */
1734 if (X509_set_pubkey(newcrt, pkey) != 1)
1735 goto mkcert_error;
1736
1737 /* Set issuer name from the CA */
1738 if (!(name = X509_get_subject_name(cacert)))
1739 goto mkcert_error;
1740 if (X509_set_issuer_name(newcrt, name) != 1)
1741 goto mkcert_error;
1742
1743 /* Set the subject name using the same, but the CN */
1744 name = X509_NAME_dup(name);
1745 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1746 (const unsigned char *)servername,
1747 -1, -1, 0) != 1) {
1748 X509_NAME_free(name);
1749 goto mkcert_error;
1750 }
1751 if (X509_set_subject_name(newcrt, name) != 1) {
1752 X509_NAME_free(name);
1753 goto mkcert_error;
1754 }
1755 X509_NAME_free(name);
1756
1757 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001758 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001759 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1760 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1761 X509_EXTENSION *ext;
1762
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001763 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001764 goto mkcert_error;
1765 if (!X509_add_ext(newcrt, ext, -1)) {
1766 X509_EXTENSION_free(ext);
1767 goto mkcert_error;
1768 }
1769 X509_EXTENSION_free(ext);
1770 }
1771
1772 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001773
1774 key_type = EVP_PKEY_base_id(capkey);
1775
1776 if (key_type == EVP_PKEY_DSA)
1777 digest = EVP_sha1();
1778 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001780 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001781 digest = EVP_sha256();
1782 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001783#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001784 int nid;
1785
1786 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1787 goto mkcert_error;
1788 if (!(digest = EVP_get_digestbynid(nid)))
1789 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001790#else
1791 goto mkcert_error;
1792#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001793 }
1794
Christopher Faulet31af49d2015-06-09 17:29:50 +02001795 if (!(X509_sign(newcrt, capkey, digest)))
1796 goto mkcert_error;
1797
1798 /* Create and set the new SSL_CTX */
1799 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1800 goto mkcert_error;
1801 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1802 goto mkcert_error;
1803 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1804 goto mkcert_error;
1805 if (!SSL_CTX_check_private_key(ssl_ctx))
1806 goto mkcert_error;
1807
1808 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001809
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001810#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001811 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001812#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001813#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1814 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001815 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001816 EC_KEY *ecc;
1817 int nid;
1818
1819 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1820 goto end;
1821 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1822 goto end;
1823 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1824 EC_KEY_free(ecc);
1825 }
1826#endif
1827 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001828 return ssl_ctx;
1829
1830 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001831 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001832 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001833 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1834 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001835 return NULL;
1836}
1837
Christopher Faulet7969a332015-10-09 11:15:03 +02001838SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001839ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001840{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001841 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001842
1843 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001844}
1845
Christopher Faulet30548802015-06-11 13:39:32 +02001846/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001847 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001848SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001849ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001850{
1851 struct lru64 *lru = NULL;
1852
1853 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001854 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001855 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001856 if (lru && lru->domain) {
1857 if (ssl)
1858 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001859 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001860 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001861 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001862 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001863 }
1864 return NULL;
1865}
1866
Emeric Brun821bb9b2017-06-15 16:37:39 +02001867/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1868 * function is not thread-safe, it should only be used to check if a certificate
1869 * exists in the lru cache (with no warranty it will not be removed by another
1870 * thread). It is kept for backward compatibility. */
1871SSL_CTX *
1872ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1873{
1874 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1875}
1876
Christopher Fauletd2cab922015-07-28 16:03:47 +02001877/* Set a certificate int the LRU cache used to store generated
1878 * certificate. Return 0 on success, otherwise -1 */
1879int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001880ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001881{
1882 struct lru64 *lru = NULL;
1883
1884 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001885 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001886 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001887 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001888 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001889 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001890 }
Christopher Faulet30548802015-06-11 13:39:32 +02001891 if (lru->domain && lru->data)
1892 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001893 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001894 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001895 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001896 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001897 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001898}
1899
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001900/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001901unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001902ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001903{
1904 return XXH32(data, len, ssl_ctx_lru_seed);
1905}
1906
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001907/* Generate a cert and immediately assign it to the SSL session so that the cert's
1908 * refcount is maintained regardless of the cert's presence in the LRU cache.
1909 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001910static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001911ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001912{
1913 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001914 SSL_CTX *ssl_ctx = NULL;
1915 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001916 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001917
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001918 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001919 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001920 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001921 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001922 if (lru && lru->domain)
1923 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001924 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001925 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001927 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001928 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001929 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001930 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001931 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001932 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001933 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001934 SSL_set_SSL_CTX(ssl, ssl_ctx);
1935 /* No LRU cache, this CTX will be released as soon as the session dies */
1936 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001937 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001938 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001939 return 0;
1940}
1941static int
1942ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1943{
1944 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001945 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001946
1947 conn_get_to_addr(conn);
1948 if (conn->flags & CO_FL_ADDR_TO_SET) {
1949 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001950 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001951 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001952 }
1953 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001954}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001955#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001956
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001957
1958#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1959#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1960#endif
1961
1962#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1963#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1964#define SSL_renegotiate_pending(arg) 0
1965#endif
1966#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1967#define SSL_OP_SINGLE_ECDH_USE 0
1968#endif
1969#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1970#define SSL_OP_NO_TICKET 0
1971#endif
1972#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1973#define SSL_OP_NO_COMPRESSION 0
1974#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001975#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1976#undef SSL_OP_NO_SSLv3
1977#define SSL_OP_NO_SSLv3 0
1978#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1980#define SSL_OP_NO_TLSv1_1 0
1981#endif
1982#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1983#define SSL_OP_NO_TLSv1_2 0
1984#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001985#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001986#define SSL_OP_NO_TLSv1_3 0
1987#endif
1988#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1989#define SSL_OP_SINGLE_DH_USE 0
1990#endif
1991#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1992#define SSL_OP_SINGLE_ECDH_USE 0
1993#endif
1994#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1995#define SSL_MODE_RELEASE_BUFFERS 0
1996#endif
1997#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1998#define SSL_MODE_SMALL_BUFFERS 0
1999#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02002000#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2001#define SSL_OP_PRIORITIZE_CHACHA 0
2002#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002003
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002004#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002005typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2006
2007static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002008{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002009#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002010 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002011 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2012#endif
2013}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2015 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002016 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2017}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002018static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002019#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002020 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002021 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2022#endif
2023}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002024static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002027 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2028#endif
2029}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002030/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002031static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2032/* Unusable in this context. */
2033static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2034static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2035static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2036static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2037static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002038#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002039typedef enum { SET_MIN, SET_MAX } set_context_func;
2040
2041static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2042 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002043 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2044}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002045static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2046 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2047 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2048}
2049static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2050 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002051 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2052}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002053static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2054 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2055 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2056}
2057static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2058 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002059 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2060}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002061static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2062 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2063 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2064}
2065static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2066 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002067 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2068}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002069static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2070 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2071 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2072}
2073static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002074#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002075 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002076 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2077#endif
2078}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002079static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2080#if SSL_OP_NO_TLSv1_3
2081 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2082 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002084}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002085#endif
2086static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2087static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002088
2089static struct {
2090 int option;
2091 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002092 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2093 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002094 const char *name;
2095} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002096 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2097 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2098 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2099 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2100 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2101 {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 +02002102};
2103
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002104static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2105{
2106 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2107 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2108 SSL_set_SSL_CTX(ssl, ctx);
2109}
2110
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002111#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002112
2113static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2114{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002115 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002117
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002118 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2119 return SSL_TLSEXT_ERR_OK;
2120 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121}
2122
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002123#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002124static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2125{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002126 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002127#else
2128static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2129{
2130#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131 struct connection *conn;
2132 struct bind_conf *s;
2133 const uint8_t *extension_data;
2134 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002135 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002136
2137 char *wildp = NULL;
2138 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002139 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002141 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002142 int i;
2143
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002144 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002145 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146
Olivier Houchard9679ac92017-10-27 14:58:08 +02002147 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002148 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002149#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002150 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2151 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002152#else
2153 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2154#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002155 /*
2156 * The server_name extension was given too much extensibility when it
2157 * was written, so parsing the normal case is a bit complex.
2158 */
2159 size_t len;
2160 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002161 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002162 /* Extract the length of the supplied list of names. */
2163 len = (*extension_data++) << 8;
2164 len |= *extension_data++;
2165 if (len + 2 != extension_len)
2166 goto abort;
2167 /*
2168 * The list in practice only has a single element, so we only consider
2169 * the first one.
2170 */
2171 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2172 goto abort;
2173 extension_len = len - 1;
2174 /* Now we can finally pull out the byte array with the actual hostname. */
2175 if (extension_len <= 2)
2176 goto abort;
2177 len = (*extension_data++) << 8;
2178 len |= *extension_data++;
2179 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2180 || memchr(extension_data, 0, len) != NULL)
2181 goto abort;
2182 servername = extension_data;
2183 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002184 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002185#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2186 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002187 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002188 }
2189#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002191 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002192 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002193 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002194 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002195 goto abort;
2196 }
2197
2198 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002199#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002200 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002201#else
2202 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2203#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002204 uint8_t sign;
2205 size_t len;
2206 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002207 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 len = (*extension_data++) << 8;
2209 len |= *extension_data++;
2210 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002211 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002212 if (len % 2 != 0)
2213 goto abort;
2214 for (; len > 0; len -= 2) {
2215 extension_data++; /* hash */
2216 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002217 switch (sign) {
2218 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002219 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 break;
2221 case TLSEXT_signature_ecdsa:
2222 has_ecdsa_sig = 1;
2223 break;
2224 default:
2225 continue;
2226 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002227 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228 break;
2229 }
2230 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002231 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002232 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233 }
2234 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002235 const SSL_CIPHER *cipher;
2236 size_t len;
2237 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002238 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002239#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002240 len = ctx->cipher_suites_len;
2241 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002242#else
2243 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2244#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002245 if (len % 2 != 0)
2246 goto abort;
2247 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002248#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002250 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002251#else
2252 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2253#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002254 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002255 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002256 break;
2257 }
2258 }
2259 }
2260
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002261 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002262 trash.area[i] = tolower(servername[i]);
2263 if (!wildp && (trash.area[i] == '.'))
2264 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002266 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002267
2268 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002269 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002270
2271 /* lookup a not neg filter */
2272 for (n = node; n; n = ebmb_next_dup(n)) {
2273 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002274 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002275 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002276 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002278 break;
2279 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002280 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002282 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002283 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 if (!node_anonymous)
2285 node_anonymous = n;
2286 break;
2287 }
2288 }
2289 }
2290 if (wildp) {
2291 /* lookup in wildcards names */
2292 node = ebst_lookup(&s->sni_w_ctx, wildp);
2293 for (n = node; n; n = ebmb_next_dup(n)) {
2294 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002295 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002297 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 break;
2300 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002301 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002302 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002303 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002304 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 if (!node_anonymous)
2306 node_anonymous = n;
2307 break;
2308 }
2309 }
2310 }
2311 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002312 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002313 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2314 : ((has_rsa_sig && node_rsa) ? node_rsa
2315 : (node_anonymous ? node_anonymous
2316 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2317 : node_rsa /* no rsa signature case (far far away) */
2318 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319 if (node) {
2320 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002321 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002322 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002323 if (conf) {
2324 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2325 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2326 if (conf->early_data)
2327 allow_early = 1;
2328 }
2329 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002330 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002331#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002332 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002333 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002334 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002335 }
2336#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002337 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002338 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002339 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002340 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002341allow_early:
2342#ifdef OPENSSL_IS_BORINGSSL
2343 if (allow_early)
2344 SSL_set_early_data_enabled(ssl, 1);
2345#else
2346 if (!allow_early)
2347 SSL_set_max_early_data(ssl, 0);
2348#endif
2349 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002350 abort:
2351 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2352 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002353#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002354 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002355#else
2356 *al = SSL_AD_UNRECOGNIZED_NAME;
2357 return 0;
2358#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359}
2360
2361#else /* OPENSSL_IS_BORINGSSL */
2362
Emeric Brunfc0421f2012-09-07 17:30:07 +02002363/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2364 * warning when no match is found, which implies the default (first) cert
2365 * will keep being used.
2366 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002367static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002368{
2369 const char *servername;
2370 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002371 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002372 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002373 int i;
2374 (void)al; /* shut gcc stupid warning */
2375
2376 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002377 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002378#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002379 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2380 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002381#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002382 if (s->strict_sni)
2383 return SSL_TLSEXT_ERR_ALERT_FATAL;
2384 ssl_sock_switchctx_set(ssl, s->default_ctx);
2385 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002386 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002387
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002388 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002389 if (!servername[i])
2390 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002391 trash.area[i] = tolower(servername[i]);
2392 if (!wildp && (trash.area[i] == '.'))
2393 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002394 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002395 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002396
2397 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002398 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002399
2400 /* lookup a not neg filter */
2401 for (n = node; n; n = ebmb_next_dup(n)) {
2402 if (!container_of(n, struct sni_ctx, name)->neg) {
2403 node = n;
2404 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002405 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002406 }
2407 if (!node && wildp) {
2408 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002409 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002410 }
2411 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002412#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002413 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2414 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002415 return SSL_TLSEXT_ERR_OK;
2416 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002417#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002418 if (s->strict_sni)
2419 return SSL_TLSEXT_ERR_ALERT_FATAL;
2420 ssl_sock_switchctx_set(ssl, s->default_ctx);
2421 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002422 }
2423
2424 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002425 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002426 return SSL_TLSEXT_ERR_OK;
2427}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002428#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002429#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2430
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002431#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002432
2433static DH * ssl_get_dh_1024(void)
2434{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002435 static unsigned char dh1024_p[]={
2436 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2437 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2438 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2439 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2440 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2441 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2442 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2443 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2444 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2445 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2446 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2447 };
2448 static unsigned char dh1024_g[]={
2449 0x02,
2450 };
2451
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002452 BIGNUM *p;
2453 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002454 DH *dh = DH_new();
2455 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2457 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002458
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002459 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002460 DH_free(dh);
2461 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002462 } else {
2463 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002464 }
2465 }
2466 return dh;
2467}
2468
2469static DH *ssl_get_dh_2048(void)
2470{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002471 static unsigned char dh2048_p[]={
2472 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2473 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2474 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2475 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2476 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2477 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2478 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2479 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2480 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2481 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2482 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2483 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2484 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2485 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2486 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2487 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2488 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2489 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2490 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2491 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2492 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2493 0xB7,0x1F,0x77,0xF3,
2494 };
2495 static unsigned char dh2048_g[]={
2496 0x02,
2497 };
2498
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002499 BIGNUM *p;
2500 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002501 DH *dh = DH_new();
2502 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002503 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2504 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002505
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002506 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002507 DH_free(dh);
2508 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002509 } else {
2510 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002511 }
2512 }
2513 return dh;
2514}
2515
2516static DH *ssl_get_dh_4096(void)
2517{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002518 static unsigned char dh4096_p[]={
2519 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2520 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2521 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2522 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2523 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2524 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2525 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2526 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2527 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2528 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2529 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2530 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2531 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2532 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2533 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2534 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2535 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2536 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2537 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2538 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2539 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2540 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2541 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2542 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2543 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2544 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2545 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2546 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2547 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2548 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2549 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2550 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2551 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2552 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2553 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2554 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2555 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2556 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2557 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2558 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2559 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2560 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2561 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002562 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002563 static unsigned char dh4096_g[]={
2564 0x02,
2565 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002566
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002567 BIGNUM *p;
2568 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002569 DH *dh = DH_new();
2570 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002571 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2572 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002573
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002574 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002575 DH_free(dh);
2576 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002577 } else {
2578 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002579 }
2580 }
2581 return dh;
2582}
2583
2584/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002585 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002586static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2587{
2588 DH *dh = NULL;
2589 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002590 int type;
2591
2592 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002593
2594 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2595 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2596 */
2597 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2598 keylen = EVP_PKEY_bits(pkey);
2599 }
2600
Willy Tarreauef934602016-12-22 23:12:01 +01002601 if (keylen > global_ssl.default_dh_param) {
2602 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002603 }
2604
Remi Gacogned3a341a2015-05-29 16:26:17 +02002605 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002606 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002607 }
2608 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002609 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002610 }
2611 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002612 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002613 }
2614
2615 return dh;
2616}
2617
Remi Gacogne47783ef2015-05-29 15:53:22 +02002618static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002619{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002620 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002621 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002622
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002623 if (in == NULL)
2624 goto end;
2625
Remi Gacogne47783ef2015-05-29 15:53:22 +02002626 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002627 goto end;
2628
Remi Gacogne47783ef2015-05-29 15:53:22 +02002629 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2630
2631end:
2632 if (in)
2633 BIO_free(in);
2634
Emeric Brune1b4ed42018-08-16 15:14:12 +02002635 ERR_clear_error();
2636
Remi Gacogne47783ef2015-05-29 15:53:22 +02002637 return dh;
2638}
2639
2640int ssl_sock_load_global_dh_param_from_file(const char *filename)
2641{
2642 global_dh = ssl_sock_get_dh_from_file(filename);
2643
2644 if (global_dh) {
2645 return 0;
2646 }
2647
2648 return -1;
2649}
2650
2651/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002652 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002653int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2654{
2655 int ret = -1;
2656 DH *dh = ssl_sock_get_dh_from_file(file);
2657
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002658 if (dh) {
2659 ret = 1;
2660 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002661
2662 if (ssl_dh_ptr_index >= 0) {
2663 /* store a pointer to the DH params to avoid complaining about
2664 ssl-default-dh-param not being set for this SSL_CTX */
2665 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2666 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002667 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002668 else if (global_dh) {
2669 SSL_CTX_set_tmp_dh(ctx, global_dh);
2670 ret = 0; /* DH params not found */
2671 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002672 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002673 /* Clear openssl global errors stack */
2674 ERR_clear_error();
2675
Willy Tarreauef934602016-12-22 23:12:01 +01002676 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002677 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002678 if (local_dh_1024 == NULL)
2679 local_dh_1024 = ssl_get_dh_1024();
2680
Remi Gacogne8de54152014-07-15 11:36:40 +02002681 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002682 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002683
Remi Gacogne8de54152014-07-15 11:36:40 +02002684 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002685 }
2686 else {
2687 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2688 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002689
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002690 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002691 }
Emeric Brun644cde02012-12-14 11:21:13 +01002692
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002693end:
2694 if (dh)
2695 DH_free(dh);
2696
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002697 return ret;
2698}
2699#endif
2700
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002701static 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 +02002702 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002703{
2704 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002705 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002706 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002707
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002708 if (*name == '!') {
2709 neg = 1;
2710 name++;
2711 }
2712 if (*name == '*') {
2713 wild = 1;
2714 name++;
2715 }
2716 /* !* filter is a nop */
2717 if (neg && wild)
2718 return order;
2719 if (*name) {
2720 int j, len;
2721 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002722 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002723 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002724 if (j >= trash.size)
2725 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002726 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002727
2728 /* Check for duplicates. */
2729 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002730 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002731 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002732 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002733 for (; node; node = ebmb_next_dup(node)) {
2734 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002735 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002736 return order;
2737 }
2738
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002739 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002740 if (!sc)
2741 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002742 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002743 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002744 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002745 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002746 sc->order = order++;
2747 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002748 if (kinfo.sig != TLSEXT_signature_anonymous)
2749 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002750 if (wild)
2751 ebst_insert(&s->sni_w_ctx, &sc->name);
2752 else
2753 ebst_insert(&s->sni_ctx, &sc->name);
2754 }
2755 return order;
2756}
2757
yanbzhu488a4d22015-12-01 15:16:07 -05002758
2759/* The following code is used for loading multiple crt files into
2760 * SSL_CTX's based on CN/SAN
2761 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002762#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002763/* This is used to preload the certifcate, private key
2764 * and Cert Chain of a file passed in via the crt
2765 * argument
2766 *
2767 * This way, we do not have to read the file multiple times
2768 */
2769struct cert_key_and_chain {
2770 X509 *cert;
2771 EVP_PKEY *key;
2772 unsigned int num_chain_certs;
2773 /* This is an array of X509 pointers */
2774 X509 **chain_certs;
2775};
2776
yanbzhu08ce6ab2015-12-02 13:01:29 -05002777#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2778
2779struct key_combo_ctx {
2780 SSL_CTX *ctx;
2781 int order;
2782};
2783
2784/* Map used for processing multiple keypairs for a single purpose
2785 *
2786 * This maps CN/SNI name to certificate type
2787 */
2788struct sni_keytype {
2789 int keytypes; /* BITMASK for keytypes */
2790 struct ebmb_node name; /* node holding the servername value */
2791};
2792
2793
yanbzhu488a4d22015-12-01 15:16:07 -05002794/* Frees the contents of a cert_key_and_chain
2795 */
2796static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2797{
2798 int i;
2799
2800 if (!ckch)
2801 return;
2802
2803 /* Free the certificate and set pointer to NULL */
2804 if (ckch->cert)
2805 X509_free(ckch->cert);
2806 ckch->cert = NULL;
2807
2808 /* Free the key and set pointer to NULL */
2809 if (ckch->key)
2810 EVP_PKEY_free(ckch->key);
2811 ckch->key = NULL;
2812
2813 /* Free each certificate in the chain */
2814 for (i = 0; i < ckch->num_chain_certs; i++) {
2815 if (ckch->chain_certs[i])
2816 X509_free(ckch->chain_certs[i]);
2817 }
2818
2819 /* Free the chain obj itself and set to NULL */
2820 if (ckch->num_chain_certs > 0) {
2821 free(ckch->chain_certs);
2822 ckch->num_chain_certs = 0;
2823 ckch->chain_certs = NULL;
2824 }
2825
2826}
2827
2828/* checks if a key and cert exists in the ckch
2829 */
2830static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2831{
2832 return (ckch->cert != NULL && ckch->key != NULL);
2833}
2834
2835
2836/* Loads the contents of a crt file (path) into a cert_key_and_chain
2837 * This allows us to carry the contents of the file without having to
2838 * read the file multiple times.
2839 *
2840 * returns:
2841 * 0 on Success
2842 * 1 on SSL Failure
2843 * 2 on file not found
2844 */
2845static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2846{
2847
2848 BIO *in;
2849 X509 *ca = NULL;
2850 int ret = 1;
2851
2852 ssl_sock_free_cert_key_and_chain_contents(ckch);
2853
2854 in = BIO_new(BIO_s_file());
2855 if (in == NULL)
2856 goto end;
2857
2858 if (BIO_read_filename(in, path) <= 0)
2859 goto end;
2860
yanbzhu488a4d22015-12-01 15:16:07 -05002861 /* Read Private Key */
2862 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2863 if (ckch->key == NULL) {
2864 memprintf(err, "%sunable to load private key from file '%s'.\n",
2865 err && *err ? *err : "", path);
2866 goto end;
2867 }
2868
Willy Tarreaubb137a82016-04-06 19:02:38 +02002869 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002870 if (BIO_reset(in) == -1) {
2871 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2872 err && *err ? *err : "", path);
2873 goto end;
2874 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002875
2876 /* Read Certificate */
2877 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2878 if (ckch->cert == NULL) {
2879 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2880 err && *err ? *err : "", path);
2881 goto end;
2882 }
2883
yanbzhu488a4d22015-12-01 15:16:07 -05002884 /* Read Certificate Chain */
2885 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2886 /* Grow the chain certs */
2887 ckch->num_chain_certs++;
2888 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2889
2890 /* use - 1 here since we just incremented it above */
2891 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2892 }
2893 ret = ERR_get_error();
2894 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2895 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2896 err && *err ? *err : "", path);
2897 ret = 1;
2898 goto end;
2899 }
2900
2901 ret = 0;
2902
2903end:
2904
2905 ERR_clear_error();
2906 if (in)
2907 BIO_free(in);
2908
2909 /* Something went wrong in one of the reads */
2910 if (ret != 0)
2911 ssl_sock_free_cert_key_and_chain_contents(ckch);
2912
2913 return ret;
2914}
2915
2916/* Loads the info in ckch into ctx
2917 * Currently, this does not process any information about ocsp, dhparams or
2918 * sctl
2919 * Returns
2920 * 0 on success
2921 * 1 on failure
2922 */
2923static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2924{
2925 int i = 0;
2926
2927 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2928 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2929 err && *err ? *err : "", path);
2930 return 1;
2931 }
2932
2933 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2934 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2935 err && *err ? *err : "", path);
2936 return 1;
2937 }
2938
yanbzhu488a4d22015-12-01 15:16:07 -05002939 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2940 for (i = 0; i < ckch->num_chain_certs; i++) {
2941 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002942 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2943 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002944 return 1;
2945 }
2946 }
2947
2948 if (SSL_CTX_check_private_key(ctx) <= 0) {
2949 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2950 err && *err ? *err : "", path);
2951 return 1;
2952 }
2953
2954 return 0;
2955}
2956
yanbzhu08ce6ab2015-12-02 13:01:29 -05002957
2958static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2959{
2960 struct sni_keytype *s_kt = NULL;
2961 struct ebmb_node *node;
2962 int i;
2963
2964 for (i = 0; i < trash.size; i++) {
2965 if (!str[i])
2966 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002967 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002968 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002969 trash.area[i] = 0;
2970 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002971 if (!node) {
2972 /* CN not found in tree */
2973 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2974 /* Using memcpy here instead of strncpy.
2975 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2976 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2977 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002978 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002979 s_kt->keytypes = 0;
2980 ebst_insert(sni_keytypes, &s_kt->name);
2981 } else {
2982 /* CN found in tree */
2983 s_kt = container_of(node, struct sni_keytype, name);
2984 }
2985
2986 /* Mark that this CN has the keytype of key_index via keytypes mask */
2987 s_kt->keytypes |= 1<<key_index;
2988
2989}
2990
2991
2992/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2993 * If any are found, group these files into a set of SSL_CTX*
2994 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2995 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08002996 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05002997 *
2998 * Returns
2999 * 0 on success
3000 * 1 on failure
3001 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003002static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3003 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003004{
3005 char fp[MAXPATHLEN+1] = {0};
3006 int n = 0;
3007 int i = 0;
3008 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3009 struct eb_root sni_keytypes_map = { {0} };
3010 struct ebmb_node *node;
3011 struct ebmb_node *next;
3012 /* Array of SSL_CTX pointers corresponding to each possible combo
3013 * of keytypes
3014 */
3015 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3016 int rv = 0;
3017 X509_NAME *xname = NULL;
3018 char *str = NULL;
3019#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3020 STACK_OF(GENERAL_NAME) *names = NULL;
3021#endif
3022
3023 /* Load all possible certs and keys */
3024 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3025 struct stat buf;
3026
3027 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3028 if (stat(fp, &buf) == 0) {
3029 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3030 rv = 1;
3031 goto end;
3032 }
3033 }
3034 }
3035
3036 /* Process each ckch and update keytypes for each CN/SAN
3037 * for example, if CN/SAN www.a.com is associated with
3038 * certs with keytype 0 and 2, then at the end of the loop,
3039 * www.a.com will have:
3040 * keyindex = 0 | 1 | 4 = 5
3041 */
3042 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3043
3044 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3045 continue;
3046
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003047 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003048 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003049 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3050 } else {
3051 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3052 * so the line that contains logic is marked via comments
3053 */
3054 xname = X509_get_subject_name(certs_and_keys[n].cert);
3055 i = -1;
3056 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3057 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003058 ASN1_STRING *value;
3059 value = X509_NAME_ENTRY_get_data(entry);
3060 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003061 /* Important line is here */
3062 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003063
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003064 OPENSSL_free(str);
3065 str = NULL;
3066 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003067 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003068
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003069 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003070#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003071 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3072 if (names) {
3073 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3074 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003075
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003076 if (name->type == GEN_DNS) {
3077 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3078 /* Important line is here */
3079 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003081 OPENSSL_free(str);
3082 str = NULL;
3083 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084 }
3085 }
3086 }
3087 }
3088#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3089 }
3090
3091 /* If no files found, return error */
3092 if (eb_is_empty(&sni_keytypes_map)) {
3093 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3094 err && *err ? *err : "", path);
3095 rv = 1;
3096 goto end;
3097 }
3098
3099 /* We now have a map of CN/SAN to keytypes that are loaded in
3100 * Iterate through the map to create the SSL_CTX's (if needed)
3101 * and add each CTX to the SNI tree
3102 *
3103 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003104 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003105 * combination is denoted by the key in the map. Each key
3106 * has a value between 1 and 2^n - 1. Conveniently, the array
3107 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3108 * entry in the array to correspond to the unique combo (key)
3109 * associated with i. This unique key combo (i) will be associated
3110 * with combos[i-1]
3111 */
3112
3113 node = ebmb_first(&sni_keytypes_map);
3114 while (node) {
3115 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003116 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003117 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003118
3119 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3120 i = container_of(node, struct sni_keytype, name)->keytypes;
3121 cur_ctx = key_combos[i-1].ctx;
3122
3123 if (cur_ctx == NULL) {
3124 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003125 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003126 if (cur_ctx == NULL) {
3127 memprintf(err, "%sunable to allocate SSL context.\n",
3128 err && *err ? *err : "");
3129 rv = 1;
3130 goto end;
3131 }
3132
yanbzhube2774d2015-12-10 15:07:30 -05003133 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003134 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3135 if (i & (1<<n)) {
3136 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003137 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3138 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003139 SSL_CTX_free(cur_ctx);
3140 rv = 1;
3141 goto end;
3142 }
yanbzhube2774d2015-12-10 15:07:30 -05003143
3144#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3145 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003146 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003147 if (err)
3148 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 +00003149 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003150 SSL_CTX_free(cur_ctx);
3151 rv = 1;
3152 goto end;
3153 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003154#elif (defined OPENSSL_IS_BORINGSSL)
3155 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003156#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003157 }
3158 }
3159
3160 /* Load DH params into the ctx to support DHE keys */
3161#ifndef OPENSSL_NO_DH
3162 if (ssl_dh_ptr_index >= 0)
3163 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3164
3165 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3166 if (rv < 0) {
3167 if (err)
3168 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3169 *err ? *err : "", path);
3170 rv = 1;
3171 goto end;
3172 }
3173#endif
3174
3175 /* Update key_combos */
3176 key_combos[i-1].ctx = cur_ctx;
3177 }
3178
3179 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003180 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003181 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003182 node = ebmb_next(node);
3183 }
3184
3185
3186 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3187 if (!bind_conf->default_ctx) {
3188 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3189 if (key_combos[i].ctx) {
3190 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003191 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003192 break;
3193 }
3194 }
3195 }
3196
3197end:
3198
3199 if (names)
3200 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3201
3202 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3203 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3204
3205 node = ebmb_first(&sni_keytypes_map);
3206 while (node) {
3207 next = ebmb_next(node);
3208 ebmb_delete(node);
3209 node = next;
3210 }
3211
3212 return rv;
3213}
3214#else
3215/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003216static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3217 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003218{
3219 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3220 err && *err ? *err : "", path, strerror(errno));
3221 return 1;
3222}
3223
yanbzhu488a4d22015-12-01 15:16:07 -05003224#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3225
Emeric Brunfc0421f2012-09-07 17:30:07 +02003226/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3227 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3228 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003229static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3230 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003231{
3232 BIO *in;
3233 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003234 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235 int ret = -1;
3236 int order = 0;
3237 X509_NAME *xname;
3238 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003239 pem_password_cb *passwd_cb;
3240 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003241 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003242 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003243
Emeric Brunfc0421f2012-09-07 17:30:07 +02003244#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3245 STACK_OF(GENERAL_NAME) *names;
3246#endif
3247
3248 in = BIO_new(BIO_s_file());
3249 if (in == NULL)
3250 goto end;
3251
3252 if (BIO_read_filename(in, file) <= 0)
3253 goto end;
3254
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003255
3256 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3257 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3258
3259 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260 if (x == NULL)
3261 goto end;
3262
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003263 pkey = X509_get_pubkey(x);
3264 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003265 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003266 switch(EVP_PKEY_base_id(pkey)) {
3267 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003268 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003269 break;
3270 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003271 kinfo.sig = TLSEXT_signature_ecdsa;
3272 break;
3273 case EVP_PKEY_DSA:
3274 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003275 break;
3276 }
3277 EVP_PKEY_free(pkey);
3278 }
3279
Emeric Brun50bcecc2013-04-22 13:05:23 +02003280 if (fcount) {
3281 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003282 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003283 }
3284 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003285#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003286 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3287 if (names) {
3288 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3289 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3290 if (name->type == GEN_DNS) {
3291 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003292 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003293 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 }
3296 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003297 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003298 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003299#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003300 xname = X509_get_subject_name(x);
3301 i = -1;
3302 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3303 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003304 ASN1_STRING *value;
3305
3306 value = X509_NAME_ENTRY_get_data(entry);
3307 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003308 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003309 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003310 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003311 }
3312 }
3313
3314 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3315 if (!SSL_CTX_use_certificate(ctx, x))
3316 goto end;
3317
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003318#ifdef SSL_CTX_clear_extra_chain_certs
3319 SSL_CTX_clear_extra_chain_certs(ctx);
3320#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003321 if (ctx->extra_certs != NULL) {
3322 sk_X509_pop_free(ctx->extra_certs, X509_free);
3323 ctx->extra_certs = NULL;
3324 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003325#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003326
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003327 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003328 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3329 X509_free(ca);
3330 goto end;
3331 }
3332 }
3333
3334 err = ERR_get_error();
3335 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3336 /* we successfully reached the last cert in the file */
3337 ret = 1;
3338 }
3339 ERR_clear_error();
3340
3341end:
3342 if (x)
3343 X509_free(x);
3344
3345 if (in)
3346 BIO_free(in);
3347
3348 return ret;
3349}
3350
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003351static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3352 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003353{
3354 int ret;
3355 SSL_CTX *ctx;
3356
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003357 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003358 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003359 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3360 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003361 return 1;
3362 }
3363
3364 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003365 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3366 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367 SSL_CTX_free(ctx);
3368 return 1;
3369 }
3370
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003371 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003372 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003373 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3374 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003375 if (ret < 0) /* serious error, must do that ourselves */
3376 SSL_CTX_free(ctx);
3377 return 1;
3378 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003379
3380 if (SSL_CTX_check_private_key(ctx) <= 0) {
3381 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3382 err && *err ? *err : "", path);
3383 return 1;
3384 }
3385
Emeric Brunfc0421f2012-09-07 17:30:07 +02003386 /* we must not free the SSL_CTX anymore below, since it's already in
3387 * the tree, so it will be discovered and cleaned in time.
3388 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003389#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003390 /* store a NULL pointer to indicate we have not yet loaded
3391 a custom DH param file */
3392 if (ssl_dh_ptr_index >= 0) {
3393 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3394 }
3395
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003396 ret = ssl_sock_load_dh_params(ctx, path);
3397 if (ret < 0) {
3398 if (err)
3399 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3400 *err ? *err : "", path);
3401 return 1;
3402 }
3403#endif
3404
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003405#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003406 ret = ssl_sock_load_ocsp(ctx, path);
3407 if (ret < 0) {
3408 if (err)
3409 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",
3410 *err ? *err : "", path);
3411 return 1;
3412 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003413#elif (defined OPENSSL_IS_BORINGSSL)
3414 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003415#endif
3416
Daniel Jakots54ffb912015-11-06 20:02:41 +01003417#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003418 if (sctl_ex_index >= 0) {
3419 ret = ssl_sock_load_sctl(ctx, path);
3420 if (ret < 0) {
3421 if (err)
3422 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3423 *err ? *err : "", path);
3424 return 1;
3425 }
3426 }
3427#endif
3428
Emeric Brunfc0421f2012-09-07 17:30:07 +02003429#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003430 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003431 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3432 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003433 return 1;
3434 }
3435#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003436 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003437 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003438 bind_conf->default_ssl_conf = ssl_conf;
3439 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003440
3441 return 0;
3442}
3443
Willy Tarreau03209342016-12-22 17:08:28 +01003444int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003445{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003446 struct dirent **de_list;
3447 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003448 DIR *dir;
3449 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003450 char *end;
3451 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003452 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003453#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3454 int is_bundle;
3455 int j;
3456#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003457
yanbzhu08ce6ab2015-12-02 13:01:29 -05003458 if (stat(path, &buf) == 0) {
3459 dir = opendir(path);
3460 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003461 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003462
yanbzhu08ce6ab2015-12-02 13:01:29 -05003463 /* strip trailing slashes, including first one */
3464 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3465 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467 n = scandir(path, &de_list, 0, alphasort);
3468 if (n < 0) {
3469 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3470 err && *err ? *err : "", path, strerror(errno));
3471 cfgerr++;
3472 }
3473 else {
3474 for (i = 0; i < n; i++) {
3475 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003476
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477 end = strrchr(de->d_name, '.');
3478 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3479 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003480
yanbzhu08ce6ab2015-12-02 13:01:29 -05003481 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3482 if (stat(fp, &buf) != 0) {
3483 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3484 err && *err ? *err : "", fp, strerror(errno));
3485 cfgerr++;
3486 goto ignore_entry;
3487 }
3488 if (!S_ISREG(buf.st_mode))
3489 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003490
3491#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3492 is_bundle = 0;
3493 /* Check if current entry in directory is part of a multi-cert bundle */
3494
3495 if (end) {
3496 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3497 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3498 is_bundle = 1;
3499 break;
3500 }
3501 }
3502
3503 if (is_bundle) {
3504 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3505 int dp_len;
3506
3507 dp_len = end - de->d_name;
3508 snprintf(dp, dp_len + 1, "%s", de->d_name);
3509
3510 /* increment i and free de until we get to a non-bundle cert
3511 * Note here that we look at de_list[i + 1] before freeing de
3512 * this is important since ignore_entry will free de
3513 */
3514 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3515 free(de);
3516 i++;
3517 de = de_list[i];
3518 }
3519
3520 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003521 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003522
3523 /* Successfully processed the bundle */
3524 goto ignore_entry;
3525 }
3526 }
3527
3528#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003529 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003530ignore_entry:
3531 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003532 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003533 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003534 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003535 closedir(dir);
3536 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003537 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003538
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003539 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003540
Emeric Brunfc0421f2012-09-07 17:30:07 +02003541 return cfgerr;
3542}
3543
Thierry Fournier383085f2013-01-24 14:15:43 +01003544/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3545 * done once. Zero is returned if the operation fails. No error is returned
3546 * if the random is said as not implemented, because we expect that openssl
3547 * will use another method once needed.
3548 */
3549static int ssl_initialize_random()
3550{
3551 unsigned char random;
3552 static int random_initialized = 0;
3553
3554 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3555 random_initialized = 1;
3556
3557 return random_initialized;
3558}
3559
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003560/* release ssl bind conf */
3561void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003562{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003563 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003564#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003565 free(conf->npn_str);
3566 conf->npn_str = NULL;
3567#endif
3568#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3569 free(conf->alpn_str);
3570 conf->alpn_str = NULL;
3571#endif
3572 free(conf->ca_file);
3573 conf->ca_file = NULL;
3574 free(conf->crl_file);
3575 conf->crl_file = NULL;
3576 free(conf->ciphers);
3577 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003578#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3579 free(conf->ciphersuites);
3580 conf->ciphersuites = NULL;
3581#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003582 free(conf->curves);
3583 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003584 free(conf->ecdhe);
3585 conf->ecdhe = NULL;
3586 }
3587}
3588
3589int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3590{
3591 char thisline[CRT_LINESIZE];
3592 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003593 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003594 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003595 int linenum = 0;
3596 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003597
Willy Tarreauad1731d2013-04-02 17:35:58 +02003598 if ((f = fopen(file, "r")) == NULL) {
3599 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003600 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003601 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003602
3603 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003604 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003606 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003607 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003608 char *crt_path;
3609 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003610
3611 linenum++;
3612 end = line + strlen(line);
3613 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3614 /* Check if we reached the limit and the last char is not \n.
3615 * Watch out for the last line without the terminating '\n'!
3616 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003617 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3618 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003619 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003620 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003621 }
3622
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003623 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003624 newarg = 1;
3625 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003626 if (*line == '#' || *line == '\n' || *line == '\r') {
3627 /* end of string, end of loop */
3628 *line = 0;
3629 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003630 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003631 newarg = 1;
3632 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003633 } else if (*line == '[') {
3634 if (ssl_b) {
3635 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3636 cfgerr = 1;
3637 break;
3638 }
3639 if (!arg) {
3640 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3641 cfgerr = 1;
3642 break;
3643 }
3644 ssl_b = arg;
3645 newarg = 1;
3646 *line = 0;
3647 } else if (*line == ']') {
3648 if (ssl_e) {
3649 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003650 cfgerr = 1;
3651 break;
3652 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003653 if (!ssl_b) {
3654 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3655 cfgerr = 1;
3656 break;
3657 }
3658 ssl_e = arg;
3659 newarg = 1;
3660 *line = 0;
3661 } else if (newarg) {
3662 if (arg == MAX_CRT_ARGS) {
3663 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3664 cfgerr = 1;
3665 break;
3666 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003667 newarg = 0;
3668 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003669 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003670 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003672 if (cfgerr)
3673 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003674 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003675
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003676 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003677 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003678 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003679
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003680 crt_path = args[0];
3681 if (*crt_path != '/' && global_ssl.crt_base) {
3682 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3683 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3684 crt_path, linenum, file);
3685 cfgerr = 1;
3686 break;
3687 }
3688 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3689 crt_path = path;
3690 }
3691
3692 ssl_conf = calloc(1, sizeof *ssl_conf);
3693 cur_arg = ssl_b ? ssl_b : 1;
3694 while (cur_arg < ssl_e) {
3695 newarg = 0;
3696 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3697 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3698 newarg = 1;
3699 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3700 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3701 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3702 args[cur_arg], linenum, file);
3703 cfgerr = 1;
3704 }
3705 cur_arg += 1 + ssl_bind_kws[i].skip;
3706 break;
3707 }
3708 }
3709 if (!cfgerr && !newarg) {
3710 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3711 args[cur_arg], linenum, file);
3712 cfgerr = 1;
3713 break;
3714 }
3715 }
3716 if (cfgerr) {
3717 ssl_sock_free_ssl_conf(ssl_conf);
3718 free(ssl_conf);
3719 ssl_conf = NULL;
3720 break;
3721 }
3722
3723 if (stat(crt_path, &buf) == 0) {
3724 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3725 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003726 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003727 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3728 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003729 }
3730
Willy Tarreauad1731d2013-04-02 17:35:58 +02003731 if (cfgerr) {
3732 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003733 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003734 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003735 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003736 fclose(f);
3737 return cfgerr;
3738}
3739
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003740/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003741static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003742ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003743{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003744 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003745 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003746 SSL_OP_ALL | /* all known workarounds for bugs */
3747 SSL_OP_NO_SSLv2 |
3748 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003749 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003750 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003751 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003752 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003753 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003754 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003755 SSL_MODE_ENABLE_PARTIAL_WRITE |
3756 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003757 SSL_MODE_RELEASE_BUFFERS |
3758 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003759 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003760 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003761 int flags = MC_SSL_O_ALL;
3762 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003763
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003764 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003765 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003766
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003767 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003768 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3769 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3770 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003771 else
3772 flags = conf_ssl_methods->flags;
3773
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003774 min = conf_ssl_methods->min;
3775 max = conf_ssl_methods->max;
3776 /* start with TLSv10 to remove SSLv3 per default */
3777 if (!min && (!max || max >= CONF_TLSV10))
3778 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003779 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003780 if (min)
3781 flags |= (methodVersions[min].flag - 1);
3782 if (max)
3783 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003784 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003785 min = max = CONF_TLSV_NONE;
3786 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003787 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003788 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003789 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003790 if (min) {
3791 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003792 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3793 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3794 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3795 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003796 hole = 0;
3797 }
3798 max = i;
3799 }
3800 else {
3801 min = max = i;
3802 }
3803 }
3804 else {
3805 if (min)
3806 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003807 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003808 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003809 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3810 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003811 cfgerr += 1;
3812 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003813 /* save real min/max in bind_conf */
3814 conf_ssl_methods->min = min;
3815 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003816
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003817#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003818 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003819 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003820 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003821 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003822 else
3823 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3824 if (flags & methodVersions[i].flag)
3825 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003826#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003827 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003828 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3829 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003830#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003831
3832 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3833 options |= SSL_OP_NO_TICKET;
3834 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3835 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3836 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003837
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003838#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003839 if (global_ssl.async)
3840 mode |= SSL_MODE_ASYNC;
3841#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003842 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003843 if (global_ssl.life_time)
3844 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003845
3846#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3847#ifdef OPENSSL_IS_BORINGSSL
3848 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3849 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003850#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3851 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3852 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003853#else
3854 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003855#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003856 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003857#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003858 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003859}
3860
William Lallemand4f45bb92017-10-30 20:08:51 +01003861
3862static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3863{
3864 if (first == block) {
3865 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3866 if (first->len > 0)
3867 sh_ssl_sess_tree_delete(sh_ssl_sess);
3868 }
3869}
3870
3871/* return first block from sh_ssl_sess */
3872static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3873{
3874 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3875
3876}
3877
3878/* store a session into the cache
3879 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3880 * data: asn1 encoded session
3881 * data_len: asn1 encoded session length
3882 * Returns 1 id session was stored (else 0)
3883 */
3884static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3885{
3886 struct shared_block *first;
3887 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3888
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003889 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003890 if (!first) {
3891 /* Could not retrieve enough free blocks to store that session */
3892 return 0;
3893 }
3894
3895 /* STORE the key in the first elem */
3896 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3897 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3898 first->len = sizeof(struct sh_ssl_sess_hdr);
3899
3900 /* it returns the already existing node
3901 or current node if none, never returns null */
3902 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3903 if (oldsh_ssl_sess != sh_ssl_sess) {
3904 /* NOTE: Row couldn't be in use because we lock read & write function */
3905 /* release the reserved row */
3906 shctx_row_dec_hot(ssl_shctx, first);
3907 /* replace the previous session already in the tree */
3908 sh_ssl_sess = oldsh_ssl_sess;
3909 /* ignore the previous session data, only use the header */
3910 first = sh_ssl_sess_first_block(sh_ssl_sess);
3911 shctx_row_inc_hot(ssl_shctx, first);
3912 first->len = sizeof(struct sh_ssl_sess_hdr);
3913 }
3914
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003915 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003916 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003917 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003918 }
3919
3920 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003921
3922 return 1;
3923}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003924
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003925/* SSL callback used when a new session is created while connecting to a server */
3926static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3927{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003928 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003929 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003930
Willy Tarreau07d94e42018-09-20 10:57:52 +02003931 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003932
Olivier Houcharde6060c52017-11-16 17:42:52 +01003933 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3934 int len;
3935 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003936
Olivier Houcharde6060c52017-11-16 17:42:52 +01003937 len = i2d_SSL_SESSION(sess, NULL);
3938 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3939 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3940 } else {
3941 free(s->ssl_ctx.reused_sess[tid].ptr);
3942 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3943 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3944 }
3945 if (s->ssl_ctx.reused_sess[tid].ptr) {
3946 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3947 &ptr);
3948 }
3949 } else {
3950 free(s->ssl_ctx.reused_sess[tid].ptr);
3951 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3952 }
3953
3954 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003955}
3956
Olivier Houcharde6060c52017-11-16 17:42:52 +01003957
William Lallemanded0b5ad2017-10-30 19:36:36 +01003958/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003959int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003960{
3961 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3962 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3963 unsigned char *p;
3964 int data_len;
3965 unsigned int sid_length, sid_ctx_length;
3966 const unsigned char *sid_data;
3967 const unsigned char *sid_ctx_data;
3968
3969 /* Session id is already stored in to key and session id is known
3970 * so we dont store it to keep size.
3971 */
3972
3973 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3974 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3975 SSL_SESSION_set1_id(sess, sid_data, 0);
3976 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3977
3978 /* check if buffer is large enough for the ASN1 encoded session */
3979 data_len = i2d_SSL_SESSION(sess, NULL);
3980 if (data_len > SHSESS_MAX_DATA_LEN)
3981 goto err;
3982
3983 p = encsess;
3984
3985 /* process ASN1 session encoding before the lock */
3986 i2d_SSL_SESSION(sess, &p);
3987
3988 memcpy(encid, sid_data, sid_length);
3989 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3990 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3991
William Lallemanda3c77cf2017-10-30 23:44:40 +01003992 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003993 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003994 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003995 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003996err:
3997 /* reset original length values */
3998 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3999 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4000
4001 return 0; /* do not increment session reference count */
4002}
4003
4004/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004005SSL_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 +01004006{
William Lallemand4f45bb92017-10-30 20:08:51 +01004007 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004008 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4009 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004010 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004011 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004012
4013 global.shctx_lookups++;
4014
4015 /* allow the session to be freed automatically by openssl */
4016 *do_copy = 0;
4017
4018 /* tree key is zeros padded sessionid */
4019 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4020 memcpy(tmpkey, key, key_len);
4021 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4022 key = tmpkey;
4023 }
4024
4025 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004026 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004027
4028 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004029 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4030 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004031 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004032 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004033 global.shctx_misses++;
4034 return NULL;
4035 }
4036
William Lallemand4f45bb92017-10-30 20:08:51 +01004037 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4038 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004039
William Lallemand4f45bb92017-10-30 20:08:51 +01004040 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 +01004041
William Lallemanda3c77cf2017-10-30 23:44:40 +01004042 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004043
4044 /* decode ASN1 session */
4045 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004046 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004047 /* Reset session id and session id contenxt */
4048 if (sess) {
4049 SSL_SESSION_set1_id(sess, key, key_len);
4050 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4051 }
4052
4053 return sess;
4054}
4055
William Lallemand4f45bb92017-10-30 20:08:51 +01004056
William Lallemanded0b5ad2017-10-30 19:36:36 +01004057/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004058void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004059{
William Lallemand4f45bb92017-10-30 20:08:51 +01004060 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004061 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4062 unsigned int sid_length;
4063 const unsigned char *sid_data;
4064 (void)ctx;
4065
4066 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4067 /* tree key is zeros padded sessionid */
4068 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4069 memcpy(tmpkey, sid_data, sid_length);
4070 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4071 sid_data = tmpkey;
4072 }
4073
William Lallemanda3c77cf2017-10-30 23:44:40 +01004074 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004075
4076 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004077 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4078 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004079 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004080 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004081 }
4082
4083 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004084 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004085}
4086
4087/* Set session cache mode to server and disable openssl internal cache.
4088 * Set shared cache callbacks on an ssl context.
4089 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004090void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004091{
4092 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4093
4094 if (!ssl_shctx) {
4095 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4096 return;
4097 }
4098
4099 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4100 SSL_SESS_CACHE_NO_INTERNAL |
4101 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4102
4103 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004104 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4105 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4106 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004107}
4108
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004109int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4110{
4111 struct proxy *curproxy = bind_conf->frontend;
4112 int cfgerr = 0;
4113 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004114 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004115 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004116#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4117 const char *conf_ciphersuites;
4118#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004119 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004120
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004121 if (ssl_conf) {
4122 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4123 int i, min, max;
4124 int flags = MC_SSL_O_ALL;
4125
4126 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004127 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4128 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004129 if (min)
4130 flags |= (methodVersions[min].flag - 1);
4131 if (max)
4132 flags |= ~((methodVersions[max].flag << 1) - 1);
4133 min = max = CONF_TLSV_NONE;
4134 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4135 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4136 if (min)
4137 max = i;
4138 else
4139 min = max = i;
4140 }
4141 /* save real min/max */
4142 conf_ssl_methods->min = min;
4143 conf_ssl_methods->max = max;
4144 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004145 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4146 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004147 cfgerr += 1;
4148 }
4149 }
4150
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004151 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004152 case SSL_SOCK_VERIFY_NONE:
4153 verify = SSL_VERIFY_NONE;
4154 break;
4155 case SSL_SOCK_VERIFY_OPTIONAL:
4156 verify = SSL_VERIFY_PEER;
4157 break;
4158 case SSL_SOCK_VERIFY_REQUIRED:
4159 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4160 break;
4161 }
4162 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4163 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004164 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4165 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4166 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004167 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004168 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004169 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4170 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004171 cfgerr++;
4172 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004173 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4174 /* set CA names for client cert request, function returns void */
4175 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4176 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004177 }
Emeric Brun850efd52014-01-29 12:24:34 +01004178 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004179 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4180 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004181 cfgerr++;
4182 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004183#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004184 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004185 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4186
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004187 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004188 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4189 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004190 cfgerr++;
4191 }
Emeric Brun561e5742012-10-02 15:20:55 +02004192 else {
4193 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4194 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004195 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004196#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004197 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004198 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004199#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004200 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004201 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004202 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4203 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004204 cfgerr++;
4205 }
4206 }
4207#endif
4208
William Lallemand4f45bb92017-10-30 20:08:51 +01004209 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004210 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4211 if (conf_ciphers &&
4212 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004213 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4214 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004215 cfgerr++;
4216 }
4217
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004218#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4219 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4220 if (conf_ciphersuites &&
4221 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4222 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4223 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4224 cfgerr++;
4225 }
4226#endif
4227
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004228#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004229 /* If tune.ssl.default-dh-param has not been set,
4230 neither has ssl-default-dh-file and no static DH
4231 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004232 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004233 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004234 (ssl_dh_ptr_index == -1 ||
4235 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004236 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4237 const SSL_CIPHER * cipher = NULL;
4238 char cipher_description[128];
4239 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4240 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4241 which is not ephemeral DH. */
4242 const char dhe_description[] = " Kx=DH ";
4243 const char dhe_export_description[] = " Kx=DH(";
4244 int idx = 0;
4245 int dhe_found = 0;
4246 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004247
Remi Gacogne23d5d372014-10-10 17:04:26 +02004248 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004249
Remi Gacogne23d5d372014-10-10 17:04:26 +02004250 if (ssl) {
4251 ciphers = SSL_get_ciphers(ssl);
4252
4253 if (ciphers) {
4254 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4255 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4256 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4257 if (strstr(cipher_description, dhe_description) != NULL ||
4258 strstr(cipher_description, dhe_export_description) != NULL) {
4259 dhe_found = 1;
4260 break;
4261 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004262 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004263 }
4264 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004265 SSL_free(ssl);
4266 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004267 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004268
Lukas Tribus90132722014-08-18 00:56:33 +02004269 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004270 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 +02004271 }
4272
Willy Tarreauef934602016-12-22 23:12:01 +01004273 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004274 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004275
Willy Tarreauef934602016-12-22 23:12:01 +01004276 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004277 if (local_dh_1024 == NULL) {
4278 local_dh_1024 = ssl_get_dh_1024();
4279 }
Willy Tarreauef934602016-12-22 23:12:01 +01004280 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004281 if (local_dh_2048 == NULL) {
4282 local_dh_2048 = ssl_get_dh_2048();
4283 }
Willy Tarreauef934602016-12-22 23:12:01 +01004284 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004285 if (local_dh_4096 == NULL) {
4286 local_dh_4096 = ssl_get_dh_4096();
4287 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004288 }
4289 }
4290 }
4291#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004292
Emeric Brunfc0421f2012-09-07 17:30:07 +02004293 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004294#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004295 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004296#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004297
Bernard Spil13c53f82018-02-15 13:34:58 +01004298#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004299 ssl_conf_cur = NULL;
4300 if (ssl_conf && ssl_conf->npn_str)
4301 ssl_conf_cur = ssl_conf;
4302 else if (bind_conf->ssl_conf.npn_str)
4303 ssl_conf_cur = &bind_conf->ssl_conf;
4304 if (ssl_conf_cur)
4305 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004306#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004307#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004308 ssl_conf_cur = NULL;
4309 if (ssl_conf && ssl_conf->alpn_str)
4310 ssl_conf_cur = ssl_conf;
4311 else if (bind_conf->ssl_conf.alpn_str)
4312 ssl_conf_cur = &bind_conf->ssl_conf;
4313 if (ssl_conf_cur)
4314 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004315#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004316#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4317 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4318 if (conf_curves) {
4319 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004320 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4321 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004322 cfgerr++;
4323 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004324#if defined(SSL_CTX_set_ecdh_auto)
4325 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4326#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004327 }
4328#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004329#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004330 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004331 int i;
4332 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004333#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004334 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004335 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4336 NULL);
4337
4338 if (ecdhe == NULL) {
4339 SSL_CTX_set_dh_auto(ctx, 1);
4340 return cfgerr;
4341 }
4342#else
4343 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4344 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4345 ECDHE_DEFAULT_CURVE);
4346#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004347
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004348 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004349 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004350 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4351 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004352 cfgerr++;
4353 }
4354 else {
4355 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4356 EC_KEY_free(ecdh);
4357 }
4358 }
4359#endif
4360
Emeric Brunfc0421f2012-09-07 17:30:07 +02004361 return cfgerr;
4362}
4363
Evan Broderbe554312013-06-27 00:05:25 -07004364static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4365{
4366 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4367 size_t prefixlen, suffixlen;
4368
4369 /* Trivial case */
4370 if (strcmp(pattern, hostname) == 0)
4371 return 1;
4372
Evan Broderbe554312013-06-27 00:05:25 -07004373 /* The rest of this logic is based on RFC 6125, section 6.4.3
4374 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4375
Emeric Bruna848dae2013-10-08 11:27:28 +02004376 pattern_wildcard = NULL;
4377 pattern_left_label_end = pattern;
4378 while (*pattern_left_label_end != '.') {
4379 switch (*pattern_left_label_end) {
4380 case 0:
4381 /* End of label not found */
4382 return 0;
4383 case '*':
4384 /* If there is more than one wildcards */
4385 if (pattern_wildcard)
4386 return 0;
4387 pattern_wildcard = pattern_left_label_end;
4388 break;
4389 }
4390 pattern_left_label_end++;
4391 }
4392
4393 /* If it's not trivial and there is no wildcard, it can't
4394 * match */
4395 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004396 return 0;
4397
4398 /* Make sure all labels match except the leftmost */
4399 hostname_left_label_end = strchr(hostname, '.');
4400 if (!hostname_left_label_end
4401 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4402 return 0;
4403
4404 /* Make sure the leftmost label of the hostname is long enough
4405 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004406 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004407 return 0;
4408
4409 /* Finally compare the string on either side of the
4410 * wildcard */
4411 prefixlen = pattern_wildcard - pattern;
4412 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004413 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4414 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004415 return 0;
4416
4417 return 1;
4418}
4419
4420static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4421{
4422 SSL *ssl;
4423 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004424 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004425 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004426
4427 int depth;
4428 X509 *cert;
4429 STACK_OF(GENERAL_NAME) *alt_names;
4430 int i;
4431 X509_NAME *cert_subject;
4432 char *str;
4433
4434 if (ok == 0)
4435 return ok;
4436
4437 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004438 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004439
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004440 /* We're checking if the provided hostnames match the desired one. The
4441 * desired hostname comes from the SNI we presented if any, or if not
4442 * provided then it may have been explicitly stated using a "verifyhost"
4443 * directive. If neither is set, we don't care about the name so the
4444 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004445 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004446 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004447 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004448 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004449 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004450 if (!servername)
4451 return ok;
4452 }
Evan Broderbe554312013-06-27 00:05:25 -07004453
4454 /* We only need to verify the CN on the actual server cert,
4455 * not the indirect CAs */
4456 depth = X509_STORE_CTX_get_error_depth(ctx);
4457 if (depth != 0)
4458 return ok;
4459
4460 /* At this point, the cert is *not* OK unless we can find a
4461 * hostname match */
4462 ok = 0;
4463
4464 cert = X509_STORE_CTX_get_current_cert(ctx);
4465 /* It seems like this might happen if verify peer isn't set */
4466 if (!cert)
4467 return ok;
4468
4469 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4470 if (alt_names) {
4471 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4472 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4473 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004474#if OPENSSL_VERSION_NUMBER < 0x00907000L
4475 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4476#else
Evan Broderbe554312013-06-27 00:05:25 -07004477 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004478#endif
Evan Broderbe554312013-06-27 00:05:25 -07004479 ok = ssl_sock_srv_hostcheck(str, servername);
4480 OPENSSL_free(str);
4481 }
4482 }
4483 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004484 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004485 }
4486
4487 cert_subject = X509_get_subject_name(cert);
4488 i = -1;
4489 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4490 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004491 ASN1_STRING *value;
4492 value = X509_NAME_ENTRY_get_data(entry);
4493 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004494 ok = ssl_sock_srv_hostcheck(str, servername);
4495 OPENSSL_free(str);
4496 }
4497 }
4498
Willy Tarreau71d058c2017-07-26 20:09:56 +02004499 /* report the mismatch and indicate if SNI was used or not */
4500 if (!ok && !conn->err_code)
4501 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004502 return ok;
4503}
4504
Emeric Brun94324a42012-10-11 14:00:19 +02004505/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004506int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004507{
Willy Tarreau03209342016-12-22 17:08:28 +01004508 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004509 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004510 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004511 SSL_OP_ALL | /* all known workarounds for bugs */
4512 SSL_OP_NO_SSLv2 |
4513 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004514 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004515 SSL_MODE_ENABLE_PARTIAL_WRITE |
4516 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004517 SSL_MODE_RELEASE_BUFFERS |
4518 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004519 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004520 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004521 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004522 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004523 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004524
Thierry Fournier383085f2013-01-24 14:15:43 +01004525 /* Make sure openssl opens /dev/urandom before the chroot */
4526 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004527 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004528 cfgerr++;
4529 }
4530
Willy Tarreaufce03112015-01-15 21:32:40 +01004531 /* Automatic memory computations need to know we use SSL there */
4532 global.ssl_used_backend = 1;
4533
4534 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004535 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004536 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004537 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4538 curproxy->id, srv->id,
4539 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004540 cfgerr++;
4541 return cfgerr;
4542 }
4543 }
Emeric Brun94324a42012-10-11 14:00:19 +02004544 if (srv->use_ssl)
4545 srv->xprt = &ssl_sock;
4546 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004547 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004548
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004549 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004550 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004551 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4552 proxy_type_str(curproxy), curproxy->id,
4553 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004554 cfgerr++;
4555 return cfgerr;
4556 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004557
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004558 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004559 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4560 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4561 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004562 else
4563 flags = conf_ssl_methods->flags;
4564
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004565 /* Real min and max should be determinate with configuration and openssl's capabilities */
4566 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004567 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004568 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004569 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004570
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004571 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004572 min = max = CONF_TLSV_NONE;
4573 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004574 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004575 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004576 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004577 if (min) {
4578 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004579 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4580 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4581 proxy_type_str(curproxy), curproxy->id, srv->id,
4582 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004583 hole = 0;
4584 }
4585 max = i;
4586 }
4587 else {
4588 min = max = i;
4589 }
4590 }
4591 else {
4592 if (min)
4593 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004594 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004595 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004596 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4597 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004598 cfgerr += 1;
4599 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004600
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004601#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004602 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004603 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004604 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004605 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004606 else
4607 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4608 if (flags & methodVersions[i].flag)
4609 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004610#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004611 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004612 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4613 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004614#endif
4615
4616 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4617 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004618 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004619
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004620#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004621 if (global_ssl.async)
4622 mode |= SSL_MODE_ASYNC;
4623#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004624 SSL_CTX_set_mode(ctx, mode);
4625 srv->ssl_ctx.ctx = ctx;
4626
Emeric Bruna7aa3092012-10-26 12:58:00 +02004627 if (srv->ssl_ctx.client_crt) {
4628 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 +01004629 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4630 proxy_type_str(curproxy), curproxy->id,
4631 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004632 cfgerr++;
4633 }
4634 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 +01004635 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4636 proxy_type_str(curproxy), curproxy->id,
4637 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004638 cfgerr++;
4639 }
4640 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004641 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4642 proxy_type_str(curproxy), curproxy->id,
4643 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004644 cfgerr++;
4645 }
4646 }
Emeric Brun94324a42012-10-11 14:00:19 +02004647
Emeric Brun850efd52014-01-29 12:24:34 +01004648 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4649 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004650 switch (srv->ssl_ctx.verify) {
4651 case SSL_SOCK_VERIFY_NONE:
4652 verify = SSL_VERIFY_NONE;
4653 break;
4654 case SSL_SOCK_VERIFY_REQUIRED:
4655 verify = SSL_VERIFY_PEER;
4656 break;
4657 }
Evan Broderbe554312013-06-27 00:05:25 -07004658 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004659 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004660 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004661 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004662 if (srv->ssl_ctx.ca_file) {
4663 /* load CAfile to verify */
4664 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004665 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4666 curproxy->id, srv->id,
4667 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004668 cfgerr++;
4669 }
4670 }
Emeric Brun850efd52014-01-29 12:24:34 +01004671 else {
4672 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004673 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",
4674 curproxy->id, srv->id,
4675 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004676 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004677 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4678 curproxy->id, srv->id,
4679 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004680 cfgerr++;
4681 }
Emeric Brunef42d922012-10-11 16:11:36 +02004682#ifdef X509_V_FLAG_CRL_CHECK
4683 if (srv->ssl_ctx.crl_file) {
4684 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4685
4686 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004687 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4688 curproxy->id, srv->id,
4689 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004690 cfgerr++;
4691 }
4692 else {
4693 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4694 }
4695 }
4696#endif
4697 }
4698
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004699 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4700 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4701 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004702 if (srv->ssl_ctx.ciphers &&
4703 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004704 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4705 curproxy->id, srv->id,
4706 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004707 cfgerr++;
4708 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004709
4710#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4711 if (srv->ssl_ctx.ciphersuites &&
4712 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4713 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4714 curproxy->id, srv->id,
4715 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4716 cfgerr++;
4717 }
4718#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004719#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4720 if (srv->ssl_ctx.npn_str)
4721 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4722#endif
4723#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4724 if (srv->ssl_ctx.alpn_str)
4725 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4726#endif
4727
Emeric Brun94324a42012-10-11 14:00:19 +02004728
4729 return cfgerr;
4730}
4731
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004732/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004733 * be NULL, in which case nothing is done. Returns the number of errors
4734 * encountered.
4735 */
Willy Tarreau03209342016-12-22 17:08:28 +01004736int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004737{
4738 struct ebmb_node *node;
4739 struct sni_ctx *sni;
4740 int err = 0;
4741
Willy Tarreaufce03112015-01-15 21:32:40 +01004742 /* Automatic memory computations need to know we use SSL there */
4743 global.ssl_used_frontend = 1;
4744
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004745 /* Make sure openssl opens /dev/urandom before the chroot */
4746 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004747 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004748 err++;
4749 }
4750 /* Create initial_ctx used to start the ssl connection before do switchctx */
4751 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004752 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004753 /* It should not be necessary to call this function, but it's
4754 necessary first to check and move all initialisation related
4755 to initial_ctx in ssl_sock_initial_ctx. */
4756 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4757 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004758 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004759 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004760
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004761 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004762 while (node) {
4763 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004764 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4765 /* only initialize the CTX on its first occurrence and
4766 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004767 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004768 node = ebmb_next(node);
4769 }
4770
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004771 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 while (node) {
4773 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004774 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4775 /* only initialize the CTX on its first occurrence and
4776 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004777 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004778 node = ebmb_next(node);
4779 }
4780 return err;
4781}
4782
Willy Tarreau55d37912016-12-21 23:38:39 +01004783/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4784 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4785 * alerts are directly emitted since the rest of the stack does it below.
4786 */
4787int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4788{
4789 struct proxy *px = bind_conf->frontend;
4790 int alloc_ctx;
4791 int err;
4792
4793 if (!bind_conf->is_ssl) {
4794 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004795 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4796 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004797 }
4798 return 0;
4799 }
4800 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004801 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004802 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4803 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004804 }
4805 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004806 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4807 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004808 return -1;
4809 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004810 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004811 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004812 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004813 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004814 sizeof(*sh_ssl_sess_tree),
4815 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004816 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004817 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4818 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");
4819 else
4820 ha_alert("Unable to allocate SSL session cache.\n");
4821 return -1;
4822 }
4823 /* free block callback */
4824 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4825 /* init the root tree within the extra space */
4826 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4827 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004828 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004829 err = 0;
4830 /* initialize all certificate contexts */
4831 err += ssl_sock_prepare_all_ctx(bind_conf);
4832
4833 /* initialize CA variables if the certificates generation is enabled */
4834 err += ssl_sock_load_ca(bind_conf);
4835
4836 return -err;
4837}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004838
4839/* release ssl context allocated for servers. */
4840void ssl_sock_free_srv_ctx(struct server *srv)
4841{
Olivier Houchardc7566002018-11-20 23:33:50 +01004842#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4843 if (srv->ssl_ctx.alpn_str)
4844 free(srv->ssl_ctx.alpn_str);
4845#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004846#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004847 if (srv->ssl_ctx.npn_str)
4848 free(srv->ssl_ctx.npn_str);
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004849 if (srv->ssl_ctx.ctx)
4850 SSL_CTX_free(srv->ssl_ctx.ctx);
Olivier Houchardc7566002018-11-20 23:33:50 +01004851#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004852}
4853
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004854/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004855 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4856 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004857void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004858{
4859 struct ebmb_node *node, *back;
4860 struct sni_ctx *sni;
4861
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004862 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004863 while (node) {
4864 sni = ebmb_entry(node, struct sni_ctx, name);
4865 back = ebmb_next(node);
4866 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004867 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004868 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004869 ssl_sock_free_ssl_conf(sni->conf);
4870 free(sni->conf);
4871 sni->conf = NULL;
4872 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004873 free(sni);
4874 node = back;
4875 }
4876
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004877 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004878 while (node) {
4879 sni = ebmb_entry(node, struct sni_ctx, name);
4880 back = ebmb_next(node);
4881 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004882 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004883 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004884 ssl_sock_free_ssl_conf(sni->conf);
4885 free(sni->conf);
4886 sni->conf = NULL;
4887 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004888 free(sni);
4889 node = back;
4890 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004891 SSL_CTX_free(bind_conf->initial_ctx);
4892 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004893 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004894 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004895}
4896
Willy Tarreau795cdab2016-12-22 17:30:54 +01004897/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4898void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4899{
4900 ssl_sock_free_ca(bind_conf);
4901 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004902 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004903 free(bind_conf->ca_sign_file);
4904 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004905 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004906 free(bind_conf->keys_ref->filename);
4907 free(bind_conf->keys_ref->tlskeys);
4908 LIST_DEL(&bind_conf->keys_ref->list);
4909 free(bind_conf->keys_ref);
4910 }
4911 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004912 bind_conf->ca_sign_pass = NULL;
4913 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004914}
4915
Christopher Faulet31af49d2015-06-09 17:29:50 +02004916/* Load CA cert file and private key used to generate certificates */
4917int
Willy Tarreau03209342016-12-22 17:08:28 +01004918ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004919{
Willy Tarreau03209342016-12-22 17:08:28 +01004920 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004921 FILE *fp;
4922 X509 *cacert = NULL;
4923 EVP_PKEY *capkey = NULL;
4924 int err = 0;
4925
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004926 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004927 return err;
4928
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004929#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004930 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004931 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004932 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004933 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004934 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004935 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004936#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004937
Christopher Faulet31af49d2015-06-09 17:29:50 +02004938 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004939 ha_alert("Proxy '%s': cannot enable certificate generation, "
4940 "no CA certificate File configured at [%s:%d].\n",
4941 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004942 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004943 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004944
4945 /* read in the CA certificate */
4946 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004947 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4948 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004949 goto load_error;
4950 }
4951 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004952 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4953 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004954 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004955 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004956 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004957 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004958 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4959 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004960 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004961 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004962
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004963 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004964 bind_conf->ca_sign_cert = cacert;
4965 bind_conf->ca_sign_pkey = capkey;
4966 return err;
4967
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004968 read_error:
4969 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004970 if (capkey) EVP_PKEY_free(capkey);
4971 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004972 load_error:
4973 bind_conf->generate_certs = 0;
4974 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004975 return err;
4976}
4977
4978/* Release CA cert and private key used to generate certificated */
4979void
4980ssl_sock_free_ca(struct bind_conf *bind_conf)
4981{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004982 if (bind_conf->ca_sign_pkey)
4983 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4984 if (bind_conf->ca_sign_cert)
4985 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004986 bind_conf->ca_sign_pkey = NULL;
4987 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004988}
4989
Emeric Brun46591952012-05-18 15:47:34 +02004990/*
4991 * This function is called if SSL * context is not yet allocated. The function
4992 * is designed to be called before any other data-layer operation and sets the
4993 * handshake flag on the connection. It is safe to call it multiple times.
4994 * It returns 0 on success and -1 in error case.
4995 */
4996static int ssl_sock_init(struct connection *conn)
4997{
4998 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004999 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005000 return 0;
5001
Willy Tarreau3c728722014-01-23 13:50:42 +01005002 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005003 return 0;
5004
Willy Tarreau20879a02012-12-03 16:32:10 +01005005 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5006 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005007 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005008 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005009
Emeric Brun46591952012-05-18 15:47:34 +02005010 /* If it is in client mode initiate SSL session
5011 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005012 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005013 int may_retry = 1;
5014
5015 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005016 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005017 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005018 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005019 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005020 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005021 goto retry_connect;
5022 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005023 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005024 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005025 }
Emeric Brun46591952012-05-18 15:47:34 +02005026
Emeric Brun46591952012-05-18 15:47:34 +02005027 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005028 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005029 SSL_free(conn->xprt_ctx);
5030 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005031 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005032 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005033 goto retry_connect;
5034 }
Emeric Brun55476152014-11-12 17:35:37 +01005035 conn->err_code = CO_ER_SSL_NO_MEM;
5036 return -1;
5037 }
Emeric Brun46591952012-05-18 15:47:34 +02005038
Evan Broderbe554312013-06-27 00:05:25 -07005039 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005040 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005041 SSL_free(conn->xprt_ctx);
5042 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005043 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005044 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005045 goto retry_connect;
5046 }
Emeric Brun55476152014-11-12 17:35:37 +01005047 conn->err_code = CO_ER_SSL_NO_MEM;
5048 return -1;
5049 }
5050
5051 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005052 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5053 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5054 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5055 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005056 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005057 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5058 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005059 } else if (sess) {
5060 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005061 }
5062 }
Evan Broderbe554312013-06-27 00:05:25 -07005063
Emeric Brun46591952012-05-18 15:47:34 +02005064 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005065 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005066
Emeric Brun7ad43e72018-10-10 14:51:02 +02005067 HA_ATOMIC_ADD(&sslconns, 1);
5068 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005069 return 0;
5070 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005071 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005072 int may_retry = 1;
5073
5074 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005075 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005076 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005077 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005078 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005079 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005080 goto retry_accept;
5081 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005082 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005083 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005084 }
Emeric Brun46591952012-05-18 15:47:34 +02005085
Emeric Brun46591952012-05-18 15:47:34 +02005086 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005087 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005088 SSL_free(conn->xprt_ctx);
5089 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005090 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005091 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005092 goto retry_accept;
5093 }
Emeric Brun55476152014-11-12 17:35:37 +01005094 conn->err_code = CO_ER_SSL_NO_MEM;
5095 return -1;
5096 }
Emeric Brun46591952012-05-18 15:47:34 +02005097
Emeric Brune1f38db2012-09-03 20:36:47 +02005098 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005099 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005100 SSL_free(conn->xprt_ctx);
5101 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005102 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005103 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005104 goto retry_accept;
5105 }
Emeric Brun55476152014-11-12 17:35:37 +01005106 conn->err_code = CO_ER_SSL_NO_MEM;
5107 return -1;
5108 }
5109
5110 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005111
Emeric Brun46591952012-05-18 15:47:34 +02005112 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005113 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005114#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005115 conn->flags |= CO_FL_EARLY_SSL_HS;
5116#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005117
Emeric Brun7ad43e72018-10-10 14:51:02 +02005118 HA_ATOMIC_ADD(&sslconns, 1);
5119 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005120 return 0;
5121 }
5122 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005123 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005124 return -1;
5125}
5126
5127
5128/* This is the callback which is used when an SSL handshake is pending. It
5129 * updates the FD status if it wants some polling before being called again.
5130 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5131 * otherwise it returns non-zero and removes itself from the connection's
5132 * flags (the bit is provided in <flag> by the caller).
5133 */
5134int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5135{
5136 int ret;
5137
Willy Tarreau3c728722014-01-23 13:50:42 +01005138 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005139 return 0;
5140
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005141 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005142 goto out_error;
5143
Olivier Houchardc2aae742017-09-22 18:26:28 +02005144#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5145 /*
5146 * Check if we have early data. If we do, we have to read them
5147 * before SSL_do_handshake() is called, And there's no way to
5148 * detect early data, except to try to read them
5149 */
5150 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5151 size_t read_data;
5152
5153 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5154 1, &read_data);
5155 if (ret == SSL_READ_EARLY_DATA_ERROR)
5156 goto check_error;
5157 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5158 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5159 return 1;
5160 } else
5161 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5162 }
5163#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005164 /* If we use SSL_do_handshake to process a reneg initiated by
5165 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5166 * Usually SSL_write and SSL_read are used and process implicitly
5167 * the reneg handshake.
5168 * Here we use SSL_peek as a workaround for reneg.
5169 */
5170 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5171 char c;
5172
5173 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5174 if (ret <= 0) {
5175 /* handshake may have not been completed, let's find why */
5176 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005177
Emeric Brun674b7432012-11-08 19:21:55 +01005178 if (ret == SSL_ERROR_WANT_WRITE) {
5179 /* SSL handshake needs to write, L4 connection may not be ready */
5180 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005181 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005182 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005183 return 0;
5184 }
5185 else if (ret == SSL_ERROR_WANT_READ) {
5186 /* handshake may have been completed but we have
5187 * no more data to read.
5188 */
5189 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5190 ret = 1;
5191 goto reneg_ok;
5192 }
5193 /* SSL handshake needs to read, L4 connection is ready */
5194 if (conn->flags & CO_FL_WAIT_L4_CONN)
5195 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5196 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005197 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005198 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005199 return 0;
5200 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005201#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005202 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005203 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005204 return 0;
5205 }
5206#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005207 else if (ret == SSL_ERROR_SYSCALL) {
5208 /* if errno is null, then connection was successfully established */
5209 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5210 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005211 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005212#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005213 conn->err_code = CO_ER_SSL_HANDSHAKE;
5214#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005215 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005216#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005217 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5218 empty_handshake = state == TLS_ST_BEFORE;
5219#else
5220 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5221#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005222 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005223 if (!errno) {
5224 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5225 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5226 else
5227 conn->err_code = CO_ER_SSL_EMPTY;
5228 }
5229 else {
5230 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5231 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5232 else
5233 conn->err_code = CO_ER_SSL_ABORT;
5234 }
5235 }
5236 else {
5237 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5238 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005239 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005240 conn->err_code = CO_ER_SSL_HANDSHAKE;
5241 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005242#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005243 }
Emeric Brun674b7432012-11-08 19:21:55 +01005244 goto out_error;
5245 }
5246 else {
5247 /* Fail on all other handshake errors */
5248 /* Note: OpenSSL may leave unread bytes in the socket's
5249 * buffer, causing an RST to be emitted upon close() on
5250 * TCP sockets. We first try to drain possibly pending
5251 * data to avoid this as much as possible.
5252 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005253 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005254 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005255 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5256 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005257 goto out_error;
5258 }
5259 }
5260 /* read some data: consider handshake completed */
5261 goto reneg_ok;
5262 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005263 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005264check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005265 if (ret != 1) {
5266 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005267 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005268
5269 if (ret == SSL_ERROR_WANT_WRITE) {
5270 /* SSL handshake needs to write, L4 connection may not be ready */
5271 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005272 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005273 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005274 return 0;
5275 }
5276 else if (ret == SSL_ERROR_WANT_READ) {
5277 /* SSL handshake needs to read, L4 connection is ready */
5278 if (conn->flags & CO_FL_WAIT_L4_CONN)
5279 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5280 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005281 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005282 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005283 return 0;
5284 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005285#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005286 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005287 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005288 return 0;
5289 }
5290#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005291 else if (ret == SSL_ERROR_SYSCALL) {
5292 /* if errno is null, then connection was successfully established */
5293 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5294 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005295 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005296#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005297 conn->err_code = CO_ER_SSL_HANDSHAKE;
5298#else
5299 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005300#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005301 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5302 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005303#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005304 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005305#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005306 if (empty_handshake) {
5307 if (!errno) {
5308 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5309 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5310 else
5311 conn->err_code = CO_ER_SSL_EMPTY;
5312 }
5313 else {
5314 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5315 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5316 else
5317 conn->err_code = CO_ER_SSL_ABORT;
5318 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005319 }
5320 else {
5321 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5322 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5323 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005324 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005325 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005326#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005327 }
Willy Tarreau89230192012-09-28 20:22:13 +02005328 goto out_error;
5329 }
Emeric Brun46591952012-05-18 15:47:34 +02005330 else {
5331 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005332 /* Note: OpenSSL may leave unread bytes in the socket's
5333 * buffer, causing an RST to be emitted upon close() on
5334 * TCP sockets. We first try to drain possibly pending
5335 * data to avoid this as much as possible.
5336 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005337 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005338 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005339 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5340 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005341 goto out_error;
5342 }
5343 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005344#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5345 else {
5346 /*
5347 * If the server refused the early data, we have to send a
5348 * 425 to the client, as we no longer have the data to sent
5349 * them again.
5350 */
5351 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5352 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5353 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5354 goto out_error;
5355 }
5356 }
5357 }
5358#endif
5359
Emeric Brun46591952012-05-18 15:47:34 +02005360
Emeric Brun674b7432012-11-08 19:21:55 +01005361reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005362
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005363#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005364 /* ASYNC engine API doesn't support moving read/write
5365 * buffers. So we disable ASYNC mode right after
5366 * the handshake to avoid buffer oveflows.
5367 */
5368 if (global_ssl.async)
5369 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5370#endif
Emeric Brun46591952012-05-18 15:47:34 +02005371 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005372 if (!SSL_session_reused(conn->xprt_ctx)) {
5373 if (objt_server(conn->target)) {
5374 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5375 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5376 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005377 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005378 else {
5379 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5380 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5381 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5382 }
Emeric Brun46591952012-05-18 15:47:34 +02005383 }
5384
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005385#ifdef OPENSSL_IS_BORINGSSL
5386 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5387 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5388#endif
Emeric Brun46591952012-05-18 15:47:34 +02005389 /* The connection is now established at both layers, it's time to leave */
5390 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5391 return 1;
5392
5393 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005394 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005395 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005396 ERR_clear_error();
5397
Emeric Brun9fa89732012-10-04 17:09:56 +02005398 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005399 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5400 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5401 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005402 }
5403
Emeric Brun46591952012-05-18 15:47:34 +02005404 /* Fail on all other handshake errors */
5405 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005406 if (!conn->err_code)
5407 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005408 return 0;
5409}
5410
5411/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005412 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005413 * buffer wraps, in which case a second call may be performed. The connection's
5414 * flags are updated with whatever special event is detected (error, read0,
5415 * empty). The caller is responsible for taking care of those events and
5416 * avoiding the call if inappropriate. The function does not call the
5417 * connection's polling update function, so the caller is responsible for this.
5418 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005419static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005420{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005421 ssize_t ret;
5422 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005423
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005424 conn_refresh_polling_flags(conn);
5425
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005426 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005427 goto out_error;
5428
5429 if (conn->flags & CO_FL_HANDSHAKE)
5430 /* a handshake was requested */
5431 return 0;
5432
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005433 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005434
5435 /* read the largest possible block. For this, we perform only one call
5436 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5437 * in which case we accept to do it once again. A new attempt is made on
5438 * EINTR too.
5439 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005440 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005441 int need_out = 0;
5442
Willy Tarreau591d4452018-06-15 17:21:00 +02005443 try = b_contig_space(buf);
5444 if (!try)
5445 break;
5446
Willy Tarreauabf08d92014-01-14 11:31:27 +01005447 if (try > count)
5448 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005449
Olivier Houchardc2aae742017-09-22 18:26:28 +02005450 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5451 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005452 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005453 done++;
5454 try--;
5455 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005456 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005457 conn->tmp_early_data = -1;
5458 continue;
5459 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005460
Olivier Houchardc2aae742017-09-22 18:26:28 +02005461#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5462 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5463 size_t read_length;
5464
5465 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005466 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005467 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5468 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005469 conn->flags |= CO_FL_EARLY_DATA;
5470 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5471 ret == SSL_READ_EARLY_DATA_FINISH) {
5472 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5473 /*
5474 * We're done reading the early data,
5475 * let's make the handshake
5476 */
5477 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5478 conn->flags |= CO_FL_SSL_WAIT_HS;
5479 need_out = 1;
5480 if (read_length == 0)
5481 break;
5482 }
5483 ret = read_length;
5484 }
5485 } else
5486#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005487 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005488#ifdef OPENSSL_IS_BORINGSSL
5489 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5490 if (SSL_in_early_data(conn->xprt_ctx)) {
5491 if (ret > 0)
5492 conn->flags |= CO_FL_EARLY_DATA;
5493 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005494 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005495 }
5496 }
5497#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005498 if (conn->flags & CO_FL_ERROR) {
5499 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005500 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005501 }
Emeric Brun46591952012-05-18 15:47:34 +02005502 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005503 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005504 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005505 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005506 }
Emeric Brun46591952012-05-18 15:47:34 +02005507 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005508 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005509 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005510 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005511 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005512 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005513#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005514 /* Async mode can be re-enabled, because we're leaving data state.*/
5515 if (global_ssl.async)
5516 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5517#endif
Emeric Brun46591952012-05-18 15:47:34 +02005518 break;
5519 }
5520 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005521 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5522 /* handshake is running, and it may need to re-enable read */
5523 conn->flags |= CO_FL_SSL_WAIT_HS;
5524 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005525#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005526 /* Async mode can be re-enabled, because we're leaving data state.*/
5527 if (global_ssl.async)
5528 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5529#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005530 break;
5531 }
Emeric Brun46591952012-05-18 15:47:34 +02005532 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005533 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005534 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005535 } else if (ret == SSL_ERROR_ZERO_RETURN)
5536 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005537 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5538 * stack before shutting down the connection for
5539 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005540 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5541 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005542 /* otherwise it's a real error */
5543 goto out_error;
5544 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005545 if (need_out)
5546 break;
Emeric Brun46591952012-05-18 15:47:34 +02005547 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005548 leave:
5549 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005550 return done;
5551
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005552 clear_ssl_error:
5553 /* Clear openssl global errors stack */
5554 ssl_sock_dump_errors(conn);
5555 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005556 read0:
5557 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005558 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005559
Emeric Brun46591952012-05-18 15:47:34 +02005560 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005561 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005562 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005563 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005564 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005565 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005566}
5567
5568
Willy Tarreau787db9a2018-06-14 18:31:46 +02005569/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5570 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5571 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005572 * Only one call to send() is performed, unless the buffer wraps, in which case
5573 * a second call may be performed. The connection's flags are updated with
5574 * whatever special event is detected (error, empty). The caller is responsible
5575 * for taking care of those events and avoiding the call if inappropriate. The
5576 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005577 * is responsible for this. The buffer's output is not adjusted, it's up to the
5578 * caller to take care of this. It's up to the caller to update the buffer's
5579 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005580 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005581static 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 +02005582{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005583 ssize_t ret;
5584 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005585
5586 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005587 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005588
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005589 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005590 goto out_error;
5591
5592 if (conn->flags & CO_FL_HANDSHAKE)
5593 /* a handshake was requested */
5594 return 0;
5595
5596 /* send the largest possible block. For this we perform only one call
5597 * to send() unless the buffer wraps and we exactly fill the first hunk,
5598 * in which case we accept to do it once again.
5599 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005600 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005601#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5602 size_t written_data;
5603#endif
5604
Willy Tarreau787db9a2018-06-14 18:31:46 +02005605 try = b_contig_data(buf, done);
5606 if (try > count)
5607 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005608
Willy Tarreau7bed9452014-02-02 02:00:24 +01005609 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005610 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005611 global_ssl.max_record && try > global_ssl.max_record) {
5612 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005613 }
5614 else {
5615 /* we need to keep the information about the fact that
5616 * we're not limiting the upcoming send(), because if it
5617 * fails, we'll have to retry with at least as many data.
5618 */
5619 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5620 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005621
Olivier Houchardc2aae742017-09-22 18:26:28 +02005622#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5623 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5624 unsigned int max_early;
5625
Olivier Houchard522eea72017-11-03 16:27:47 +01005626 if (objt_listener(conn->target))
5627 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5628 else {
5629 if (SSL_get0_session(conn->xprt_ctx))
5630 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5631 else
5632 max_early = 0;
5633 }
5634
Olivier Houchard90084a12017-11-23 18:21:29 +01005635 if (try + conn->sent_early_data > max_early) {
5636 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005637 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005638 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5639 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005640 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005641 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005642 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005643 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005644 if (ret == 1) {
5645 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005646 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005647 if (objt_server(conn->target)) {
5648 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5649 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5650 }
5651
Olivier Houchardc2aae742017-09-22 18:26:28 +02005652 }
5653
5654 } else
5655#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005656 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005657
Emeric Brune1f38db2012-09-03 20:36:47 +02005658 if (conn->flags & CO_FL_ERROR) {
5659 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005660 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005661 }
Emeric Brun46591952012-05-18 15:47:34 +02005662 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005663 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005664 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005665 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005666 }
5667 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005668 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005669
Emeric Brun46591952012-05-18 15:47:34 +02005670 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005671 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5672 /* handshake is running, and it may need to re-enable write */
5673 conn->flags |= CO_FL_SSL_WAIT_HS;
5674 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005675#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005676 /* Async mode can be re-enabled, because we're leaving data state.*/
5677 if (global_ssl.async)
5678 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5679#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005680 break;
5681 }
Emeric Brun46591952012-05-18 15:47:34 +02005682 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005683 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005684 break;
5685 }
5686 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005687 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005688 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005689 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005690#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005691 /* Async mode can be re-enabled, because we're leaving data state.*/
5692 if (global_ssl.async)
5693 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5694#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005695 break;
5696 }
Emeric Brun46591952012-05-18 15:47:34 +02005697 goto out_error;
5698 }
5699 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005700 leave:
5701 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005702 return done;
5703
5704 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005705 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005706 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005707 ERR_clear_error();
5708
Emeric Brun46591952012-05-18 15:47:34 +02005709 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005710 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005711}
5712
Emeric Brun46591952012-05-18 15:47:34 +02005713static void ssl_sock_close(struct connection *conn) {
5714
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005715 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005716#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005717 if (global_ssl.async) {
5718 OSSL_ASYNC_FD all_fd[32], afd;
5719 size_t num_all_fds = 0;
5720 int i;
5721
5722 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5723 if (num_all_fds > 32) {
5724 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5725 return;
5726 }
5727
5728 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5729
5730 /* If an async job is pending, we must try to
5731 to catch the end using polling before calling
5732 SSL_free */
5733 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5734 for (i=0 ; i < num_all_fds ; i++) {
5735 /* switch on an handler designed to
5736 * handle the SSL_free
5737 */
5738 afd = all_fd[i];
5739 fdtab[afd].iocb = ssl_async_fd_free;
5740 fdtab[afd].owner = conn->xprt_ctx;
5741 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005742 /* To ensure that the fd cache won't be used
5743 * and we'll catch a real RD event.
5744 */
5745 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005746 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005747 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005748 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005749 return;
5750 }
Emeric Brun3854e012017-05-17 20:42:48 +02005751 /* Else we can remove the fds from the fdtab
5752 * and call SSL_free.
5753 * note: we do a fd_remove and not a delete
5754 * because the fd is owned by the engine.
5755 * the engine is responsible to close
5756 */
5757 for (i=0 ; i < num_all_fds ; i++)
5758 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005759 }
5760#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005761 SSL_free(conn->xprt_ctx);
5762 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005763 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005764 }
Emeric Brun46591952012-05-18 15:47:34 +02005765}
5766
5767/* This function tries to perform a clean shutdown on an SSL connection, and in
5768 * any case, flags the connection as reusable if no handshake was in progress.
5769 */
5770static void ssl_sock_shutw(struct connection *conn, int clean)
5771{
5772 if (conn->flags & CO_FL_HANDSHAKE)
5773 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005774 if (!clean)
5775 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005776 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005777 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005778 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005779 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005780 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005781 ERR_clear_error();
5782 }
Emeric Brun46591952012-05-18 15:47:34 +02005783}
5784
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005785/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005786int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005787{
5788 struct pkey_info *pkinfo;
5789 int bits = 0;
5790 int sig = TLSEXT_signature_anonymous;
5791 int len = -1;
5792
5793 if (!ssl_sock_is_ssl(conn))
5794 return 0;
5795
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005796 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005797 if (pkinfo) {
5798 sig = pkinfo->sig;
5799 bits = pkinfo->bits;
5800 } else {
5801 /* multicert and generated cert have no pkey info */
5802 X509 *crt;
5803 EVP_PKEY *pkey;
5804 crt = SSL_get_certificate(conn->xprt_ctx);
5805 if (!crt)
5806 return 0;
5807 pkey = X509_get_pubkey(crt);
5808 if (pkey) {
5809 bits = EVP_PKEY_bits(pkey);
5810 switch(EVP_PKEY_base_id(pkey)) {
5811 case EVP_PKEY_RSA:
5812 sig = TLSEXT_signature_rsa;
5813 break;
5814 case EVP_PKEY_EC:
5815 sig = TLSEXT_signature_ecdsa;
5816 break;
5817 case EVP_PKEY_DSA:
5818 sig = TLSEXT_signature_dsa;
5819 break;
5820 }
5821 EVP_PKEY_free(pkey);
5822 }
5823 }
5824
5825 switch(sig) {
5826 case TLSEXT_signature_rsa:
5827 len = chunk_printf(out, "RSA%d", bits);
5828 break;
5829 case TLSEXT_signature_ecdsa:
5830 len = chunk_printf(out, "EC%d", bits);
5831 break;
5832 case TLSEXT_signature_dsa:
5833 len = chunk_printf(out, "DSA%d", bits);
5834 break;
5835 default:
5836 return 0;
5837 }
5838 if (len < 0)
5839 return 0;
5840 return 1;
5841}
5842
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005843/* used for ppv2 cert signature (can be used for logging) */
5844const char *ssl_sock_get_cert_sig(struct connection *conn)
5845{
5846 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5847 X509 *crt;
5848
5849 if (!ssl_sock_is_ssl(conn))
5850 return NULL;
5851 crt = SSL_get_certificate(conn->xprt_ctx);
5852 if (!crt)
5853 return NULL;
5854 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5855 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5856}
5857
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005858/* used for ppv2 authority */
5859const char *ssl_sock_get_sni(struct connection *conn)
5860{
5861#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5862 if (!ssl_sock_is_ssl(conn))
5863 return NULL;
5864 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5865#else
5866 return 0;
5867#endif
5868}
5869
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005870/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005871const char *ssl_sock_get_cipher_name(struct connection *conn)
5872{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005873 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005874 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005875
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005876 return SSL_get_cipher_name(conn->xprt_ctx);
5877}
5878
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005879/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005880const char *ssl_sock_get_proto_version(struct connection *conn)
5881{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005882 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005883 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005884
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005885 return SSL_get_version(conn->xprt_ctx);
5886}
5887
Willy Tarreau8d598402012-10-22 17:58:39 +02005888/* Extract a serial from a cert, and copy it to a chunk.
5889 * Returns 1 if serial is found and copied, 0 if no serial found and
5890 * -1 if output is not large enough.
5891 */
5892static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005893ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005894{
5895 ASN1_INTEGER *serial;
5896
5897 serial = X509_get_serialNumber(crt);
5898 if (!serial)
5899 return 0;
5900
5901 if (out->size < serial->length)
5902 return -1;
5903
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005904 memcpy(out->area, serial->data, serial->length);
5905 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005906 return 1;
5907}
5908
Emeric Brun43e79582014-10-29 19:03:26 +01005909/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005910 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5911 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005912 */
5913static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005914ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005915{
5916 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005917 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005918
5919 len =i2d_X509(crt, NULL);
5920 if (len <= 0)
5921 return 1;
5922
5923 if (out->size < len)
5924 return -1;
5925
5926 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005927 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005928 return 1;
5929}
5930
Emeric Brunce5ad802012-10-22 14:11:22 +02005931
Willy Tarreau83061a82018-07-13 11:56:34 +02005932/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005933 * Returns 1 if serial is found and copied, 0 if no valid time found
5934 * and -1 if output is not large enough.
5935 */
5936static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005937ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005938{
5939 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5940 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5941
5942 if (gentm->length < 12)
5943 return 0;
5944 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5945 return 0;
5946 if (out->size < gentm->length-2)
5947 return -1;
5948
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005949 memcpy(out->area, gentm->data+2, gentm->length-2);
5950 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005951 return 1;
5952 }
5953 else if (tm->type == V_ASN1_UTCTIME) {
5954 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5955
5956 if (utctm->length < 10)
5957 return 0;
5958 if (utctm->data[0] >= 0x35)
5959 return 0;
5960 if (out->size < utctm->length)
5961 return -1;
5962
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005963 memcpy(out->area, utctm->data, utctm->length);
5964 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005965 return 1;
5966 }
5967
5968 return 0;
5969}
5970
Emeric Brun87855892012-10-17 17:39:35 +02005971/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5972 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5973 */
5974static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005975ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5976 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005977{
5978 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005979 ASN1_OBJECT *obj;
5980 ASN1_STRING *data;
5981 const unsigned char *data_ptr;
5982 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005983 int i, j, n;
5984 int cur = 0;
5985 const char *s;
5986 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005987 int name_count;
5988
5989 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005990
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005991 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005992 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005993 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005994 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005995 else
5996 j = i;
5997
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005998 ne = X509_NAME_get_entry(a, j);
5999 obj = X509_NAME_ENTRY_get_object(ne);
6000 data = X509_NAME_ENTRY_get_data(ne);
6001 data_ptr = ASN1_STRING_get0_data(data);
6002 data_len = ASN1_STRING_length(data);
6003 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006004 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006005 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006006 s = tmp;
6007 }
6008
6009 if (chunk_strcasecmp(entry, s) != 0)
6010 continue;
6011
6012 if (pos < 0)
6013 cur--;
6014 else
6015 cur++;
6016
6017 if (cur != pos)
6018 continue;
6019
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006020 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006021 return -1;
6022
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006023 memcpy(out->area, data_ptr, data_len);
6024 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006025 return 1;
6026 }
6027
6028 return 0;
6029
6030}
6031
6032/* Extract and format full DN from a X509_NAME and copy result into a chunk
6033 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6034 */
6035static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006036ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006037{
6038 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006039 ASN1_OBJECT *obj;
6040 ASN1_STRING *data;
6041 const unsigned char *data_ptr;
6042 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006043 int i, n, ln;
6044 int l = 0;
6045 const char *s;
6046 char *p;
6047 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006048 int name_count;
6049
6050
6051 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006052
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006053 out->data = 0;
6054 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006055 for (i = 0; i < name_count; i++) {
6056 ne = X509_NAME_get_entry(a, i);
6057 obj = X509_NAME_ENTRY_get_object(ne);
6058 data = X509_NAME_ENTRY_get_data(ne);
6059 data_ptr = ASN1_STRING_get0_data(data);
6060 data_len = ASN1_STRING_length(data);
6061 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006062 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006063 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006064 s = tmp;
6065 }
6066 ln = strlen(s);
6067
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006068 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006069 if (l > out->size)
6070 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006071 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006072
6073 *(p++)='/';
6074 memcpy(p, s, ln);
6075 p += ln;
6076 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006077 memcpy(p, data_ptr, data_len);
6078 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006079 }
6080
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006081 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006082 return 0;
6083
6084 return 1;
6085}
6086
Willy Tarreau119a4082016-12-22 21:58:38 +01006087/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6088 * to disable SNI.
6089 */
Willy Tarreau63076412015-07-10 11:33:32 +02006090void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6091{
6092#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006093 char *prev_name;
6094
Willy Tarreau63076412015-07-10 11:33:32 +02006095 if (!ssl_sock_is_ssl(conn))
6096 return;
6097
Willy Tarreau119a4082016-12-22 21:58:38 +01006098 /* if the SNI changes, we must destroy the reusable context so that a
6099 * new connection will present a new SNI. As an optimization we could
6100 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6101 * server.
6102 */
6103 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6104 if ((!prev_name && hostname) ||
6105 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6106 SSL_set_session(conn->xprt_ctx, NULL);
6107
Willy Tarreau63076412015-07-10 11:33:32 +02006108 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6109#endif
6110}
6111
Emeric Brun0abf8362014-06-24 18:26:41 +02006112/* Extract peer certificate's common name into the chunk dest
6113 * Returns
6114 * the len of the extracted common name
6115 * or 0 if no CN found in DN
6116 * or -1 on error case (i.e. no peer certificate)
6117 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006118int ssl_sock_get_remote_common_name(struct connection *conn,
6119 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006120{
6121 X509 *crt = NULL;
6122 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006123 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006124 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006125 .area = (char *)&find_cn,
6126 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006127 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006128 int result = -1;
David Safb76832014-05-08 23:42:08 -04006129
6130 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006131 goto out;
David Safb76832014-05-08 23:42:08 -04006132
6133 /* SSL_get_peer_certificate, it increase X509 * ref count */
6134 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6135 if (!crt)
6136 goto out;
6137
6138 name = X509_get_subject_name(crt);
6139 if (!name)
6140 goto out;
David Safb76832014-05-08 23:42:08 -04006141
Emeric Brun0abf8362014-06-24 18:26:41 +02006142 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6143out:
David Safb76832014-05-08 23:42:08 -04006144 if (crt)
6145 X509_free(crt);
6146
6147 return result;
6148}
6149
Dave McCowan328fb582014-07-30 10:39:13 -04006150/* returns 1 if client passed a certificate for this session, 0 if not */
6151int ssl_sock_get_cert_used_sess(struct connection *conn)
6152{
6153 X509 *crt = NULL;
6154
6155 if (!ssl_sock_is_ssl(conn))
6156 return 0;
6157
6158 /* SSL_get_peer_certificate, it increase X509 * ref count */
6159 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6160 if (!crt)
6161 return 0;
6162
6163 X509_free(crt);
6164 return 1;
6165}
6166
6167/* returns 1 if client passed a certificate for this connection, 0 if not */
6168int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006169{
6170 if (!ssl_sock_is_ssl(conn))
6171 return 0;
6172
6173 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6174}
6175
6176/* returns result from SSL verify */
6177unsigned int ssl_sock_get_verify_result(struct connection *conn)
6178{
6179 if (!ssl_sock_is_ssl(conn))
6180 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6181
6182 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6183}
6184
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006185/* Returns the application layer protocol name in <str> and <len> when known.
6186 * Zero is returned if the protocol name was not found, otherwise non-zero is
6187 * returned. The string is allocated in the SSL context and doesn't have to be
6188 * freed by the caller. NPN is also checked if available since older versions
6189 * of openssl (1.0.1) which are more common in field only support this one.
6190 */
6191static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6192{
6193 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6194 return 0;
6195
6196 *str = NULL;
6197
6198#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6199 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6200 if (*str)
6201 return 1;
6202#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006203#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006204 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6205 if (*str)
6206 return 1;
6207#endif
6208 return 0;
6209}
6210
Willy Tarreau7875d092012-09-10 08:20:03 +02006211/***** Below are some sample fetching functions for ACL/patterns *****/
6212
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006213static int
6214smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6215{
6216 struct connection *conn;
6217
6218 conn = objt_conn(smp->sess->origin);
6219 if (!conn || conn->xprt != &ssl_sock)
6220 return 0;
6221
6222 smp->flags = 0;
6223 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006224 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6225 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006226
6227 return 1;
6228}
6229
Emeric Brune64aef12012-09-21 13:15:06 +02006230/* boolean, returns true if client cert was present */
6231static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006232smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006233{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006234 struct connection *conn;
6235
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006236 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006237 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006238 return 0;
6239
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006240 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006241 smp->flags |= SMP_F_MAY_CHANGE;
6242 return 0;
6243 }
6244
6245 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006246 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006247 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006248
6249 return 1;
6250}
6251
Emeric Brun43e79582014-10-29 19:03:26 +01006252/* binary, returns a certificate in a binary chunk (der/raw).
6253 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6254 * should be use.
6255 */
6256static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006257smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006258{
6259 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6260 X509 *crt = NULL;
6261 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006262 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006263 struct connection *conn;
6264
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006265 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006266 if (!conn || conn->xprt != &ssl_sock)
6267 return 0;
6268
6269 if (!(conn->flags & CO_FL_CONNECTED)) {
6270 smp->flags |= SMP_F_MAY_CHANGE;
6271 return 0;
6272 }
6273
6274 if (cert_peer)
6275 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6276 else
6277 crt = SSL_get_certificate(conn->xprt_ctx);
6278
6279 if (!crt)
6280 goto out;
6281
6282 smp_trash = get_trash_chunk();
6283 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6284 goto out;
6285
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006286 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006287 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006288 ret = 1;
6289out:
6290 /* SSL_get_peer_certificate, it increase X509 * ref count */
6291 if (cert_peer && crt)
6292 X509_free(crt);
6293 return ret;
6294}
6295
Emeric Brunba841a12014-04-30 17:05:08 +02006296/* binary, returns serial of certificate in a binary chunk.
6297 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6298 * should be use.
6299 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006300static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006301smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006302{
Emeric Brunba841a12014-04-30 17:05:08 +02006303 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006304 X509 *crt = NULL;
6305 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006306 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006307 struct connection *conn;
6308
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006309 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006310 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006311 return 0;
6312
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006313 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006314 smp->flags |= SMP_F_MAY_CHANGE;
6315 return 0;
6316 }
6317
Emeric Brunba841a12014-04-30 17:05:08 +02006318 if (cert_peer)
6319 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6320 else
6321 crt = SSL_get_certificate(conn->xprt_ctx);
6322
Willy Tarreau8d598402012-10-22 17:58:39 +02006323 if (!crt)
6324 goto out;
6325
Willy Tarreau47ca5452012-12-23 20:22:19 +01006326 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006327 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6328 goto out;
6329
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006330 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006331 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006332 ret = 1;
6333out:
Emeric Brunba841a12014-04-30 17:05:08 +02006334 /* SSL_get_peer_certificate, it increase X509 * ref count */
6335 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006336 X509_free(crt);
6337 return ret;
6338}
Emeric Brune64aef12012-09-21 13:15:06 +02006339
Emeric Brunba841a12014-04-30 17:05:08 +02006340/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6341 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6342 * should be use.
6343 */
James Votha051b4a2013-05-14 20:37:59 +02006344static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006345smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006346{
Emeric Brunba841a12014-04-30 17:05:08 +02006347 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006348 X509 *crt = NULL;
6349 const EVP_MD *digest;
6350 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006351 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006352 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006353
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006354 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006355 if (!conn || conn->xprt != &ssl_sock)
6356 return 0;
6357
6358 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006359 smp->flags |= SMP_F_MAY_CHANGE;
6360 return 0;
6361 }
6362
Emeric Brunba841a12014-04-30 17:05:08 +02006363 if (cert_peer)
6364 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6365 else
6366 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006367 if (!crt)
6368 goto out;
6369
6370 smp_trash = get_trash_chunk();
6371 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006372 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6373 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006374
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006375 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006376 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006377 ret = 1;
6378out:
Emeric Brunba841a12014-04-30 17:05:08 +02006379 /* SSL_get_peer_certificate, it increase X509 * ref count */
6380 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006381 X509_free(crt);
6382 return ret;
6383}
6384
Emeric Brunba841a12014-04-30 17:05:08 +02006385/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6386 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6387 * should be use.
6388 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006389static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006390smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006391{
Emeric Brunba841a12014-04-30 17:05:08 +02006392 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006393 X509 *crt = NULL;
6394 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006395 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006396 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006397
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006398 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006399 if (!conn || conn->xprt != &ssl_sock)
6400 return 0;
6401
6402 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006403 smp->flags |= SMP_F_MAY_CHANGE;
6404 return 0;
6405 }
6406
Emeric Brunba841a12014-04-30 17:05:08 +02006407 if (cert_peer)
6408 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6409 else
6410 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006411 if (!crt)
6412 goto out;
6413
Willy Tarreau47ca5452012-12-23 20:22:19 +01006414 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006415 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6416 goto out;
6417
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006418 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006419 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006420 ret = 1;
6421out:
Emeric Brunba841a12014-04-30 17:05:08 +02006422 /* SSL_get_peer_certificate, it increase X509 * ref count */
6423 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006424 X509_free(crt);
6425 return ret;
6426}
6427
Emeric Brunba841a12014-04-30 17:05:08 +02006428/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6429 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6430 * should be use.
6431 */
Emeric Brun87855892012-10-17 17:39:35 +02006432static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006433smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006434{
Emeric Brunba841a12014-04-30 17:05:08 +02006435 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006436 X509 *crt = NULL;
6437 X509_NAME *name;
6438 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006439 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006440 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006441
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006442 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006443 if (!conn || conn->xprt != &ssl_sock)
6444 return 0;
6445
6446 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006447 smp->flags |= SMP_F_MAY_CHANGE;
6448 return 0;
6449 }
6450
Emeric Brunba841a12014-04-30 17:05:08 +02006451 if (cert_peer)
6452 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6453 else
6454 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006455 if (!crt)
6456 goto out;
6457
6458 name = X509_get_issuer_name(crt);
6459 if (!name)
6460 goto out;
6461
Willy Tarreau47ca5452012-12-23 20:22:19 +01006462 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006463 if (args && args[0].type == ARGT_STR) {
6464 int pos = 1;
6465
6466 if (args[1].type == ARGT_SINT)
6467 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006468
6469 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6470 goto out;
6471 }
6472 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6473 goto out;
6474
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006475 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006476 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006477 ret = 1;
6478out:
Emeric Brunba841a12014-04-30 17:05:08 +02006479 /* SSL_get_peer_certificate, it increase X509 * ref count */
6480 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006481 X509_free(crt);
6482 return ret;
6483}
6484
Emeric Brunba841a12014-04-30 17:05:08 +02006485/* string, returns notbefore date in ASN1_UTCTIME format.
6486 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6487 * should be use.
6488 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006489static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006490smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006491{
Emeric Brunba841a12014-04-30 17:05:08 +02006492 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006493 X509 *crt = NULL;
6494 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006495 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006496 struct connection *conn;
6497
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006498 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006499 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006500 return 0;
6501
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006502 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006503 smp->flags |= SMP_F_MAY_CHANGE;
6504 return 0;
6505 }
6506
Emeric Brunba841a12014-04-30 17:05:08 +02006507 if (cert_peer)
6508 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6509 else
6510 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006511 if (!crt)
6512 goto out;
6513
Willy Tarreau47ca5452012-12-23 20:22:19 +01006514 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006515 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6516 goto out;
6517
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006518 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006519 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006520 ret = 1;
6521out:
Emeric Brunba841a12014-04-30 17:05:08 +02006522 /* SSL_get_peer_certificate, it increase X509 * ref count */
6523 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006524 X509_free(crt);
6525 return ret;
6526}
6527
Emeric Brunba841a12014-04-30 17:05:08 +02006528/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6529 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6530 * should be use.
6531 */
Emeric Brun87855892012-10-17 17:39:35 +02006532static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006533smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006534{
Emeric Brunba841a12014-04-30 17:05:08 +02006535 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006536 X509 *crt = NULL;
6537 X509_NAME *name;
6538 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006539 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006540 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006541
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006542 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006543 if (!conn || conn->xprt != &ssl_sock)
6544 return 0;
6545
6546 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006547 smp->flags |= SMP_F_MAY_CHANGE;
6548 return 0;
6549 }
6550
Emeric Brunba841a12014-04-30 17:05:08 +02006551 if (cert_peer)
6552 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6553 else
6554 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006555 if (!crt)
6556 goto out;
6557
6558 name = X509_get_subject_name(crt);
6559 if (!name)
6560 goto out;
6561
Willy Tarreau47ca5452012-12-23 20:22:19 +01006562 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006563 if (args && args[0].type == ARGT_STR) {
6564 int pos = 1;
6565
6566 if (args[1].type == ARGT_SINT)
6567 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006568
6569 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6570 goto out;
6571 }
6572 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6573 goto out;
6574
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006575 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006576 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006577 ret = 1;
6578out:
Emeric Brunba841a12014-04-30 17:05:08 +02006579 /* SSL_get_peer_certificate, it increase X509 * ref count */
6580 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006581 X509_free(crt);
6582 return ret;
6583}
Emeric Brun9143d372012-12-20 15:44:16 +01006584
6585/* integer, returns true if current session use a client certificate */
6586static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006587smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006588{
6589 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006590 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006591
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006592 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006593 if (!conn || conn->xprt != &ssl_sock)
6594 return 0;
6595
6596 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006597 smp->flags |= SMP_F_MAY_CHANGE;
6598 return 0;
6599 }
6600
6601 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006602 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006603 if (crt) {
6604 X509_free(crt);
6605 }
6606
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006607 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006608 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006609 return 1;
6610}
6611
Emeric Brunba841a12014-04-30 17:05:08 +02006612/* integer, returns the certificate version
6613 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6614 * should be use.
6615 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006616static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006617smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006618{
Emeric Brunba841a12014-04-30 17:05:08 +02006619 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006620 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006621 struct connection *conn;
6622
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006623 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006624 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006625 return 0;
6626
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006627 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006628 smp->flags |= SMP_F_MAY_CHANGE;
6629 return 0;
6630 }
6631
Emeric Brunba841a12014-04-30 17:05:08 +02006632 if (cert_peer)
6633 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6634 else
6635 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006636 if (!crt)
6637 return 0;
6638
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006639 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006640 /* SSL_get_peer_certificate increase X509 * ref count */
6641 if (cert_peer)
6642 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006643 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006644
6645 return 1;
6646}
6647
Emeric Brunba841a12014-04-30 17:05:08 +02006648/* string, returns the certificate's signature algorithm.
6649 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6650 * should be use.
6651 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006652static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006653smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006654{
Emeric Brunba841a12014-04-30 17:05:08 +02006655 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006656 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006657 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006658 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006659 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006660
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006661 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006662 if (!conn || conn->xprt != &ssl_sock)
6663 return 0;
6664
6665 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006666 smp->flags |= SMP_F_MAY_CHANGE;
6667 return 0;
6668 }
6669
Emeric Brunba841a12014-04-30 17:05:08 +02006670 if (cert_peer)
6671 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6672 else
6673 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006674 if (!crt)
6675 return 0;
6676
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006677 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6678 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006679
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006680 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6681 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006682 /* SSL_get_peer_certificate increase X509 * ref count */
6683 if (cert_peer)
6684 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006685 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006686 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006687
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006688 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006689 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006690 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006691 /* SSL_get_peer_certificate increase X509 * ref count */
6692 if (cert_peer)
6693 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006694
6695 return 1;
6696}
6697
Emeric Brunba841a12014-04-30 17:05:08 +02006698/* string, returns the certificate's key algorithm.
6699 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6700 * should be use.
6701 */
Emeric Brun521a0112012-10-22 12:22:55 +02006702static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006703smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006704{
Emeric Brunba841a12014-04-30 17:05:08 +02006705 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006706 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006707 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006708 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006709 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006710
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006711 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006712 if (!conn || conn->xprt != &ssl_sock)
6713 return 0;
6714
6715 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006716 smp->flags |= SMP_F_MAY_CHANGE;
6717 return 0;
6718 }
6719
Emeric Brunba841a12014-04-30 17:05:08 +02006720 if (cert_peer)
6721 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6722 else
6723 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006724 if (!crt)
6725 return 0;
6726
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006727 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6728 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006729
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006730 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6731 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006732 /* SSL_get_peer_certificate increase X509 * ref count */
6733 if (cert_peer)
6734 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006735 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006736 }
Emeric Brun521a0112012-10-22 12:22:55 +02006737
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006738 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006739 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006740 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006741 if (cert_peer)
6742 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006743
6744 return 1;
6745}
6746
Emeric Brun645ae792014-04-30 14:21:06 +02006747/* boolean, returns true if front conn. transport layer is SSL.
6748 * This function is also usable on backend conn if the fetch keyword 5th
6749 * char is 'b'.
6750 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006751static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006752smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006753{
Emeric Bruneb8def92018-02-19 15:59:48 +01006754 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6755 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006756
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006757 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006758 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006759 return 1;
6760}
6761
Emeric Brun2525b6b2012-10-18 15:59:43 +02006762/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006763static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006764smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006765{
6766#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006767 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006768
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006769 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006770 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006771 conn->xprt_ctx &&
6772 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006773 return 1;
6774#else
6775 return 0;
6776#endif
6777}
6778
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006779/* boolean, returns true if client session has been resumed.
6780 * This function is also usable on backend conn if the fetch keyword 5th
6781 * char is 'b'.
6782 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006783static int
6784smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6785{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006786 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6787 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6788
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006789
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006790 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006791 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006792 conn->xprt_ctx &&
6793 SSL_session_reused(conn->xprt_ctx);
6794 return 1;
6795}
6796
Emeric Brun645ae792014-04-30 14:21:06 +02006797/* string, returns the used cipher if front conn. transport layer is SSL.
6798 * This function is also usable on backend conn if the fetch keyword 5th
6799 * char is 'b'.
6800 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006801static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006802smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006803{
Emeric Bruneb8def92018-02-19 15:59:48 +01006804 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6805 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006806
Willy Tarreaube508f12016-03-10 11:47:01 +01006807 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006808 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006809 return 0;
6810
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006811 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6812 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006813 return 0;
6814
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006815 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006816 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006817 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006818
6819 return 1;
6820}
6821
Emeric Brun645ae792014-04-30 14:21:06 +02006822/* integer, returns the algoritm's keysize if front conn. transport layer
6823 * is SSL.
6824 * This function is also usable on backend conn if the fetch keyword 5th
6825 * char is 'b'.
6826 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006827static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006828smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006829{
Emeric Bruneb8def92018-02-19 15:59:48 +01006830 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6831 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006832 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006833
Emeric Brun589fcad2012-10-16 14:13:26 +02006834 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006835 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006836 return 0;
6837
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006838 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006839 return 0;
6840
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006841 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006842 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006843
6844 return 1;
6845}
6846
Emeric Brun645ae792014-04-30 14:21:06 +02006847/* integer, returns the used keysize if front conn. transport layer is SSL.
6848 * This function is also usable on backend conn if the fetch keyword 5th
6849 * char is 'b'.
6850 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006851static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006852smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006853{
Emeric Bruneb8def92018-02-19 15:59:48 +01006854 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6855 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006856
Emeric Brun589fcad2012-10-16 14:13:26 +02006857 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006858 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6859 return 0;
6860
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006861 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6862 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006863 return 0;
6864
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006865 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006866
6867 return 1;
6868}
6869
Bernard Spil13c53f82018-02-15 13:34:58 +01006870#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006871static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006872smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006873{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006874 struct connection *conn;
6875
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006876 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006877 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006878
Olivier Houchard6b77f492018-11-22 18:18:29 +01006879 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6880 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006881 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6882 return 0;
6883
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006884 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006885 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006886 (const unsigned char **)&smp->data.u.str.area,
6887 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006888
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006889 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006890 return 0;
6891
6892 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006893}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006894#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006895
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006896#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006897static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006898smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006899{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006900 struct connection *conn;
6901
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006902 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006903 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006904
Olivier Houchard6b77f492018-11-22 18:18:29 +01006905 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6906 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6907
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006908 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006909 return 0;
6910
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006911 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006912 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006913 (const unsigned char **)&smp->data.u.str.area,
6914 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006915
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006916 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006917 return 0;
6918
6919 return 1;
6920}
6921#endif
6922
Emeric Brun645ae792014-04-30 14:21:06 +02006923/* string, returns the used protocol if front conn. transport layer is SSL.
6924 * This function is also usable on backend conn if the fetch keyword 5th
6925 * char is 'b'.
6926 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006927static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006928smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006929{
Emeric Bruneb8def92018-02-19 15:59:48 +01006930 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6931 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006932
Emeric Brun589fcad2012-10-16 14:13:26 +02006933 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006934 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6935 return 0;
6936
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006937 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6938 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006939 return 0;
6940
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006941 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006942 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006943 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006944
6945 return 1;
6946}
6947
Willy Tarreau87b09662015-04-03 00:22:06 +02006948/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006949 * This function is also usable on backend conn if the fetch keyword 5th
6950 * char is 'b'.
6951 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006952#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006953static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006954smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006955{
Emeric Bruneb8def92018-02-19 15:59:48 +01006956 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6957 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006958 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006959
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006960 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006961 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006962
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006963 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6964 return 0;
6965
Willy Tarreau192252e2015-04-04 01:47:55 +02006966 ssl_sess = SSL_get_session(conn->xprt_ctx);
6967 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006968 return 0;
6969
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006970 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6971 (unsigned int *)&smp->data.u.str.data);
6972 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006973 return 0;
6974
6975 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006976}
Patrick Hemmer41966772018-04-28 19:15:48 -04006977#endif
6978
Emeric Brunfe68f682012-10-16 14:59:28 +02006979
Patrick Hemmere0275472018-04-28 19:15:51 -04006980#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6981static int
6982smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6983{
6984 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6985 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6986 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006987 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006988
6989 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6990 return 0;
6991
6992 ssl_sess = SSL_get_session(conn->xprt_ctx);
6993 if (!ssl_sess)
6994 return 0;
6995
6996 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006997 data->data = SSL_SESSION_get_master_key(ssl_sess,
6998 (unsigned char *) data->area,
6999 data->size);
7000 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007001 return 0;
7002
7003 smp->flags = 0;
7004 smp->data.type = SMP_T_BIN;
7005 smp->data.u.str = *data;
7006
7007 return 1;
7008}
7009#endif
7010
Patrick Hemmer41966772018-04-28 19:15:48 -04007011#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007012static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007013smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007014{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007015 struct connection *conn;
7016
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007017 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007018 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007019
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007020 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007021 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7022 return 0;
7023
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007024 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7025 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007026 return 0;
7027
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007028 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007029 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007030}
Patrick Hemmer41966772018-04-28 19:15:48 -04007031#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007032
David Sc1ad52e2014-04-08 18:48:47 -04007033static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007034smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7035{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007036 struct connection *conn;
7037 struct ssl_capture *capture;
7038
7039 conn = objt_conn(smp->sess->origin);
7040 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7041 return 0;
7042
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007043 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007044 if (!capture)
7045 return 0;
7046
7047 smp->flags = SMP_F_CONST;
7048 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007049 smp->data.u.str.area = capture->ciphersuite;
7050 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007051 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007052}
7053
7054static int
7055smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7056{
Willy Tarreau83061a82018-07-13 11:56:34 +02007057 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007058
7059 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7060 return 0;
7061
7062 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007063 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007064 smp->data.type = SMP_T_BIN;
7065 smp->data.u.str = *data;
7066 return 1;
7067}
7068
7069static int
7070smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7071{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007072 struct connection *conn;
7073 struct ssl_capture *capture;
7074
7075 conn = objt_conn(smp->sess->origin);
7076 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7077 return 0;
7078
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007079 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007080 if (!capture)
7081 return 0;
7082
7083 smp->data.type = SMP_T_SINT;
7084 smp->data.u.sint = capture->xxh64;
7085 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007086}
7087
7088static int
7089smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7090{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007091#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007092 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007093 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007094
7095 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7096 return 0;
7097
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007098 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007099 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007100 const char *str;
7101 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007102 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007103 uint16_t id = (bin[0] << 8) | bin[1];
7104#if defined(OPENSSL_IS_BORINGSSL)
7105 cipher = SSL_get_cipher_by_value(id);
7106#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007107 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007108 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7109#endif
7110 str = SSL_CIPHER_get_name(cipher);
7111 if (!str || strcmp(str, "(NONE)") == 0)
7112 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007113 else
7114 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7115 }
7116 smp->data.type = SMP_T_STR;
7117 smp->data.u.str = *data;
7118 return 1;
7119#else
7120 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7121#endif
7122}
7123
Patrick Hemmer41966772018-04-28 19:15:48 -04007124#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007125static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007126smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007127{
Emeric Bruneb8def92018-02-19 15:59:48 +01007128 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7129 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007130 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007131 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007132
7133 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007134 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7135 return 0;
7136
7137 if (!(conn->flags & CO_FL_CONNECTED)) {
7138 smp->flags |= SMP_F_MAY_CHANGE;
7139 return 0;
7140 }
7141
7142 finished_trash = get_trash_chunk();
7143 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007144 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7145 finished_trash->area,
7146 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007147 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007148 finished_len = SSL_get_finished(conn->xprt_ctx,
7149 finished_trash->area,
7150 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007151
7152 if (!finished_len)
7153 return 0;
7154
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007155 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007156 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007157 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007158
7159 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007160}
Patrick Hemmer41966772018-04-28 19:15:48 -04007161#endif
David Sc1ad52e2014-04-08 18:48:47 -04007162
Emeric Brun2525b6b2012-10-18 15:59:43 +02007163/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007164static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007165smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007166{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007167 struct connection *conn;
7168
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007169 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007170 if (!conn || conn->xprt != &ssl_sock)
7171 return 0;
7172
7173 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007174 smp->flags = SMP_F_MAY_CHANGE;
7175 return 0;
7176 }
7177
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007178 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007179 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007180 smp->flags = 0;
7181
7182 return 1;
7183}
7184
Emeric Brun2525b6b2012-10-18 15:59:43 +02007185/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007186static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007187smp_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 +02007188{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007189 struct connection *conn;
7190
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007191 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007192 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007193 return 0;
7194
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007195 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007196 smp->flags = SMP_F_MAY_CHANGE;
7197 return 0;
7198 }
7199
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007200 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007201 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007202 smp->flags = 0;
7203
7204 return 1;
7205}
7206
Emeric Brun2525b6b2012-10-18 15:59:43 +02007207/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007208static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007209smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007210{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007211 struct connection *conn;
7212
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007213 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007214 if (!conn || conn->xprt != &ssl_sock)
7215 return 0;
7216
7217 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007218 smp->flags = SMP_F_MAY_CHANGE;
7219 return 0;
7220 }
7221
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007222 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007223 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007224 smp->flags = 0;
7225
7226 return 1;
7227}
7228
Emeric Brun2525b6b2012-10-18 15:59:43 +02007229/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007230static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007231smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007232{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007233 struct connection *conn;
7234
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007235 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007236 if (!conn || conn->xprt != &ssl_sock)
7237 return 0;
7238
7239 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007240 smp->flags = SMP_F_MAY_CHANGE;
7241 return 0;
7242 }
7243
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007244 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007245 return 0;
7246
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007247 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007248 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007249 smp->flags = 0;
7250
7251 return 1;
7252}
7253
Emeric Brunfb510ea2012-10-05 12:00:26 +02007254/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007255static 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 +02007256{
7257 if (!*args[cur_arg + 1]) {
7258 if (err)
7259 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7260 return ERR_ALERT | ERR_FATAL;
7261 }
7262
Willy Tarreauef934602016-12-22 23:12:01 +01007263 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7264 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007265 else
7266 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007267
Emeric Brund94b3fe2012-09-20 18:23:56 +02007268 return 0;
7269}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007270static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7271{
7272 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7273}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007274
Christopher Faulet31af49d2015-06-09 17:29:50 +02007275/* parse the "ca-sign-file" bind keyword */
7276static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7277{
7278 if (!*args[cur_arg + 1]) {
7279 if (err)
7280 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7281 return ERR_ALERT | ERR_FATAL;
7282 }
7283
Willy Tarreauef934602016-12-22 23:12:01 +01007284 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7285 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007286 else
7287 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7288
7289 return 0;
7290}
7291
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007292/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007293static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7294{
7295 if (!*args[cur_arg + 1]) {
7296 if (err)
7297 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7298 return ERR_ALERT | ERR_FATAL;
7299 }
7300 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7301 return 0;
7302}
7303
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007304/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007305static 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 +02007306{
7307 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007308 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007309 return ERR_ALERT | ERR_FATAL;
7310 }
7311
Emeric Brun76d88952012-10-05 15:47:31 +02007312 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007313 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007314 return 0;
7315}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007316static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7317{
7318 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7319}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007320
7321#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7322/* parse the "ciphersuites" bind keyword */
7323static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7324{
7325 if (!*args[cur_arg + 1]) {
7326 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7327 return ERR_ALERT | ERR_FATAL;
7328 }
7329
7330 free(conf->ciphersuites);
7331 conf->ciphersuites = strdup(args[cur_arg + 1]);
7332 return 0;
7333}
7334static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7335{
7336 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7337}
7338#endif
7339
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007340/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007341static 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 +02007342{
Willy Tarreau38011032013-08-13 16:59:39 +02007343 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007344
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007345 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007346 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007347 return ERR_ALERT | ERR_FATAL;
7348 }
7349
Willy Tarreauef934602016-12-22 23:12:01 +01007350 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7351 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007352 memprintf(err, "'%s' : path too long", args[cur_arg]);
7353 return ERR_ALERT | ERR_FATAL;
7354 }
Willy Tarreauef934602016-12-22 23:12:01 +01007355 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007356 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007357 return ERR_ALERT | ERR_FATAL;
7358
7359 return 0;
7360 }
7361
Willy Tarreau03209342016-12-22 17:08:28 +01007362 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007363 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007364
7365 return 0;
7366}
7367
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007368/* parse the "crt-list" bind keyword */
7369static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7370{
7371 if (!*args[cur_arg + 1]) {
7372 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7373 return ERR_ALERT | ERR_FATAL;
7374 }
7375
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007376 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007377 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007378 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007379 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007380
7381 return 0;
7382}
7383
Emeric Brunfb510ea2012-10-05 12:00:26 +02007384/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007385static 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 +02007386{
Emeric Brun051cdab2012-10-02 19:25:50 +02007387#ifndef X509_V_FLAG_CRL_CHECK
7388 if (err)
7389 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7390 return ERR_ALERT | ERR_FATAL;
7391#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007392 if (!*args[cur_arg + 1]) {
7393 if (err)
7394 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7395 return ERR_ALERT | ERR_FATAL;
7396 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007397
Willy Tarreauef934602016-12-22 23:12:01 +01007398 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7399 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007400 else
7401 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007402
Emeric Brun2b58d042012-09-20 17:10:03 +02007403 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007404#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007405}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007406static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7407{
7408 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7409}
Emeric Brun2b58d042012-09-20 17:10:03 +02007410
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007411/* parse the "curves" bind keyword keyword */
7412static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7413{
7414#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7415 if (!*args[cur_arg + 1]) {
7416 if (err)
7417 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7418 return ERR_ALERT | ERR_FATAL;
7419 }
7420 conf->curves = strdup(args[cur_arg + 1]);
7421 return 0;
7422#else
7423 if (err)
7424 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7425 return ERR_ALERT | ERR_FATAL;
7426#endif
7427}
7428static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7429{
7430 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7431}
7432
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007433/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007434static 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 +02007435{
7436#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7437 if (err)
7438 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7439 return ERR_ALERT | ERR_FATAL;
7440#elif defined(OPENSSL_NO_ECDH)
7441 if (err)
7442 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7443 return ERR_ALERT | ERR_FATAL;
7444#else
7445 if (!*args[cur_arg + 1]) {
7446 if (err)
7447 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7448 return ERR_ALERT | ERR_FATAL;
7449 }
7450
7451 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007452
7453 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007454#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007455}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007456static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7457{
7458 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7459}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007460
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007461/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007462static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7463{
7464 int code;
7465 char *p = args[cur_arg + 1];
7466 unsigned long long *ignerr = &conf->crt_ignerr;
7467
7468 if (!*p) {
7469 if (err)
7470 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7471 return ERR_ALERT | ERR_FATAL;
7472 }
7473
7474 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7475 ignerr = &conf->ca_ignerr;
7476
7477 if (strcmp(p, "all") == 0) {
7478 *ignerr = ~0ULL;
7479 return 0;
7480 }
7481
7482 while (p) {
7483 code = atoi(p);
7484 if ((code <= 0) || (code > 63)) {
7485 if (err)
7486 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7487 args[cur_arg], code, args[cur_arg + 1]);
7488 return ERR_ALERT | ERR_FATAL;
7489 }
7490 *ignerr |= 1ULL << code;
7491 p = strchr(p, ',');
7492 if (p)
7493 p++;
7494 }
7495
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007496 return 0;
7497}
7498
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007499/* parse tls_method_options "no-xxx" and "force-xxx" */
7500static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007501{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007502 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007503 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007504 p = strchr(arg, '-');
7505 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007506 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007507 p++;
7508 if (!strcmp(p, "sslv3"))
7509 v = CONF_SSLV3;
7510 else if (!strcmp(p, "tlsv10"))
7511 v = CONF_TLSV10;
7512 else if (!strcmp(p, "tlsv11"))
7513 v = CONF_TLSV11;
7514 else if (!strcmp(p, "tlsv12"))
7515 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007516 else if (!strcmp(p, "tlsv13"))
7517 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007518 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007519 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007520 if (!strncmp(arg, "no-", 3))
7521 methods->flags |= methodVersions[v].flag;
7522 else if (!strncmp(arg, "force-", 6))
7523 methods->min = methods->max = v;
7524 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007525 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007526 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007527 fail:
7528 if (err)
7529 memprintf(err, "'%s' : option not implemented", arg);
7530 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007531}
7532
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007533static 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 +02007534{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007535 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007536}
7537
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007538static 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 +02007539{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007540 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7541}
7542
7543/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7544static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7545{
7546 uint16_t i, v = 0;
7547 char *argv = args[cur_arg + 1];
7548 if (!*argv) {
7549 if (err)
7550 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7551 return ERR_ALERT | ERR_FATAL;
7552 }
7553 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7554 if (!strcmp(argv, methodVersions[i].name))
7555 v = i;
7556 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007557 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007558 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007559 return ERR_ALERT | ERR_FATAL;
7560 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007561 if (!strcmp("ssl-min-ver", args[cur_arg]))
7562 methods->min = v;
7563 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7564 methods->max = v;
7565 else {
7566 if (err)
7567 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7568 return ERR_ALERT | ERR_FATAL;
7569 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007570 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007571}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007572
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007573static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7574{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007575#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007576 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 +02007577#endif
7578 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7579}
7580
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007581static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7582{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007583 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007584}
7585
7586static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7587{
7588 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7589}
7590
Emeric Brun2d0c4822012-10-02 13:45:20 +02007591/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007592static 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 +02007593{
Emeric Brun89675492012-10-05 13:48:26 +02007594 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007595 return 0;
7596}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007597
Olivier Houchardc2aae742017-09-22 18:26:28 +02007598/* parse the "allow-0rtt" bind keyword */
7599static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7600{
7601 conf->early_data = 1;
7602 return 0;
7603}
7604
7605static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7606{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007607 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007608 return 0;
7609}
7610
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007611/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007612static 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 +02007613{
Bernard Spil13c53f82018-02-15 13:34:58 +01007614#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007615 char *p1, *p2;
7616
7617 if (!*args[cur_arg + 1]) {
7618 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7619 return ERR_ALERT | ERR_FATAL;
7620 }
7621
7622 free(conf->npn_str);
7623
Willy Tarreau3724da12016-02-12 17:11:12 +01007624 /* the NPN string is built as a suite of (<len> <name>)*,
7625 * so we reuse each comma to store the next <len> and need
7626 * one more for the end of the string.
7627 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007628 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007629 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007630 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7631
7632 /* replace commas with the name length */
7633 p1 = conf->npn_str;
7634 p2 = p1 + 1;
7635 while (1) {
7636 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7637 if (!p2)
7638 p2 = p1 + 1 + strlen(p1 + 1);
7639
7640 if (p2 - (p1 + 1) > 255) {
7641 *p2 = '\0';
7642 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7643 return ERR_ALERT | ERR_FATAL;
7644 }
7645
7646 *p1 = p2 - (p1 + 1);
7647 p1 = p2;
7648
7649 if (!*p2)
7650 break;
7651
7652 *(p2++) = '\0';
7653 }
7654 return 0;
7655#else
7656 if (err)
7657 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7658 return ERR_ALERT | ERR_FATAL;
7659#endif
7660}
7661
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007662static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7663{
7664 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7665}
7666
Willy Tarreauab861d32013-04-02 02:30:41 +02007667/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007668static 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 +02007669{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007670#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007671 char *p1, *p2;
7672
7673 if (!*args[cur_arg + 1]) {
7674 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7675 return ERR_ALERT | ERR_FATAL;
7676 }
7677
7678 free(conf->alpn_str);
7679
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007680 /* the ALPN string is built as a suite of (<len> <name>)*,
7681 * so we reuse each comma to store the next <len> and need
7682 * one more for the end of the string.
7683 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007684 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007685 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007686 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7687
7688 /* replace commas with the name length */
7689 p1 = conf->alpn_str;
7690 p2 = p1 + 1;
7691 while (1) {
7692 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7693 if (!p2)
7694 p2 = p1 + 1 + strlen(p1 + 1);
7695
7696 if (p2 - (p1 + 1) > 255) {
7697 *p2 = '\0';
7698 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7699 return ERR_ALERT | ERR_FATAL;
7700 }
7701
7702 *p1 = p2 - (p1 + 1);
7703 p1 = p2;
7704
7705 if (!*p2)
7706 break;
7707
7708 *(p2++) = '\0';
7709 }
7710 return 0;
7711#else
7712 if (err)
7713 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7714 return ERR_ALERT | ERR_FATAL;
7715#endif
7716}
7717
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007718static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7719{
7720 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7721}
7722
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007723/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007724static 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 +02007725{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007726 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007727 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007728
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007729 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7730 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007731#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7732 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7733 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7734#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007735 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007736 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7737 if (!conf->ssl_conf.ssl_methods.min)
7738 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7739 if (!conf->ssl_conf.ssl_methods.max)
7740 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007741
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007742 return 0;
7743}
7744
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007745/* parse the "prefer-client-ciphers" bind keyword */
7746static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7747{
7748 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7749 return 0;
7750}
7751
Christopher Faulet31af49d2015-06-09 17:29:50 +02007752/* parse the "generate-certificates" bind keyword */
7753static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7754{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007755#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007756 conf->generate_certs = 1;
7757#else
7758 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7759 err && *err ? *err : "");
7760#endif
7761 return 0;
7762}
7763
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007764/* parse the "strict-sni" bind keyword */
7765static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7766{
7767 conf->strict_sni = 1;
7768 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007769}
7770
7771/* parse the "tls-ticket-keys" bind keyword */
7772static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7773{
7774#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7775 FILE *f;
7776 int i = 0;
7777 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007778 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007779
7780 if (!*args[cur_arg + 1]) {
7781 if (err)
7782 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7783 return ERR_ALERT | ERR_FATAL;
7784 }
7785
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007786 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007787 if (keys_ref) {
7788 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007789 conf->keys_ref = keys_ref;
7790 return 0;
7791 }
7792
Vincent Bernat02779b62016-04-03 13:48:43 +02007793 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007794 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007795
7796 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7797 if (err)
7798 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7799 return ERR_ALERT | ERR_FATAL;
7800 }
7801
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007802 keys_ref->filename = strdup(args[cur_arg + 1]);
7803
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007804 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7805 int len = strlen(thisline);
7806 /* Strip newline characters from the end */
7807 if(thisline[len - 1] == '\n')
7808 thisline[--len] = 0;
7809
7810 if(thisline[len - 1] == '\r')
7811 thisline[--len] = 0;
7812
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007813 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 +01007814 if (err)
7815 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007816 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007817 return ERR_ALERT | ERR_FATAL;
7818 }
7819 i++;
7820 }
7821
7822 if (i < TLS_TICKETS_NO) {
7823 if (err)
7824 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 +02007825 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007826 return ERR_ALERT | ERR_FATAL;
7827 }
7828
7829 fclose(f);
7830
7831 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007832 i -= 2;
7833 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007834 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007835 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007836 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007837 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007838
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007839 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7840
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007841 return 0;
7842#else
7843 if (err)
7844 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7845 return ERR_ALERT | ERR_FATAL;
7846#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007847}
7848
Emeric Brund94b3fe2012-09-20 18:23:56 +02007849/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007850static 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 +02007851{
7852 if (!*args[cur_arg + 1]) {
7853 if (err)
7854 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7855 return ERR_ALERT | ERR_FATAL;
7856 }
7857
7858 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007859 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007860 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007861 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007862 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007863 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007864 else {
7865 if (err)
7866 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7867 args[cur_arg], args[cur_arg + 1]);
7868 return ERR_ALERT | ERR_FATAL;
7869 }
7870
7871 return 0;
7872}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007873static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7874{
7875 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7876}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007877
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007878/* parse the "no-ca-names" bind keyword */
7879static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7880{
7881 conf->no_ca_names = 1;
7882 return 0;
7883}
7884static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7885{
7886 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7887}
7888
Willy Tarreau92faadf2012-10-10 23:04:25 +02007889/************** "server" keywords ****************/
7890
Olivier Houchardc7566002018-11-20 23:33:50 +01007891/* parse the "npn" bind keyword */
7892static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7893{
7894#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7895 char *p1, *p2;
7896
7897 if (!*args[*cur_arg + 1]) {
7898 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7899 return ERR_ALERT | ERR_FATAL;
7900 }
7901
7902 free(newsrv->ssl_ctx.npn_str);
7903
7904 /* the NPN string is built as a suite of (<len> <name>)*,
7905 * so we reuse each comma to store the next <len> and need
7906 * one more for the end of the string.
7907 */
7908 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7909 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7910 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7911 newsrv->ssl_ctx.npn_len);
7912
7913 /* replace commas with the name length */
7914 p1 = newsrv->ssl_ctx.npn_str;
7915 p2 = p1 + 1;
7916 while (1) {
7917 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7918 newsrv->ssl_ctx.npn_len - (p1 + 1));
7919 if (!p2)
7920 p2 = p1 + 1 + strlen(p1 + 1);
7921
7922 if (p2 - (p1 + 1) > 255) {
7923 *p2 = '\0';
7924 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7925 return ERR_ALERT | ERR_FATAL;
7926 }
7927
7928 *p1 = p2 - (p1 + 1);
7929 p1 = p2;
7930
7931 if (!*p2)
7932 break;
7933
7934 *(p2++) = '\0';
7935 }
7936 return 0;
7937#else
7938 if (err)
7939 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7940 return ERR_ALERT | ERR_FATAL;
7941#endif
7942}
7943
7944/* parse the "alpn" bind keyword */
7945static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7946{
7947#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7948 char *p1, *p2;
7949
7950 if (!*args[*cur_arg + 1]) {
7951 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7952 return ERR_ALERT | ERR_FATAL;
7953 }
7954
7955 free(newsrv->ssl_ctx.alpn_str);
7956
7957 /* the ALPN string is built as a suite of (<len> <name>)*,
7958 * so we reuse each comma to store the next <len> and need
7959 * one more for the end of the string.
7960 */
7961 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7962 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7963 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7964 newsrv->ssl_ctx.alpn_len);
7965
7966 /* replace commas with the name length */
7967 p1 = newsrv->ssl_ctx.alpn_str;
7968 p2 = p1 + 1;
7969 while (1) {
7970 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7971 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7972 if (!p2)
7973 p2 = p1 + 1 + strlen(p1 + 1);
7974
7975 if (p2 - (p1 + 1) > 255) {
7976 *p2 = '\0';
7977 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7978 return ERR_ALERT | ERR_FATAL;
7979 }
7980
7981 *p1 = p2 - (p1 + 1);
7982 p1 = p2;
7983
7984 if (!*p2)
7985 break;
7986
7987 *(p2++) = '\0';
7988 }
7989 return 0;
7990#else
7991 if (err)
7992 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
7993 return ERR_ALERT | ERR_FATAL;
7994#endif
7995}
7996
Emeric Brunef42d922012-10-11 16:11:36 +02007997/* parse the "ca-file" server keyword */
7998static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7999{
8000 if (!*args[*cur_arg + 1]) {
8001 if (err)
8002 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8003 return ERR_ALERT | ERR_FATAL;
8004 }
8005
Willy Tarreauef934602016-12-22 23:12:01 +01008006 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8007 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008008 else
8009 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8010
8011 return 0;
8012}
8013
Olivier Houchard9130a962017-10-17 17:33:43 +02008014/* parse the "check-sni" server keyword */
8015static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8016{
8017 if (!*args[*cur_arg + 1]) {
8018 if (err)
8019 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8020 return ERR_ALERT | ERR_FATAL;
8021 }
8022
8023 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8024 if (!newsrv->check.sni) {
8025 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8026 return ERR_ALERT | ERR_FATAL;
8027 }
8028 return 0;
8029
8030}
8031
Willy Tarreau92faadf2012-10-10 23:04:25 +02008032/* parse the "check-ssl" server keyword */
8033static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8034{
8035 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008036 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8037 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008038#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8039 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8040 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8041#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008042 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008043 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8044 if (!newsrv->ssl_ctx.methods.min)
8045 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8046 if (!newsrv->ssl_ctx.methods.max)
8047 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8048
Willy Tarreau92faadf2012-10-10 23:04:25 +02008049 return 0;
8050}
8051
8052/* parse the "ciphers" server keyword */
8053static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8054{
8055 if (!*args[*cur_arg + 1]) {
8056 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8057 return ERR_ALERT | ERR_FATAL;
8058 }
8059
8060 free(newsrv->ssl_ctx.ciphers);
8061 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8062 return 0;
8063}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008064
8065#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8066/* parse the "ciphersuites" server keyword */
8067static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8068{
8069 if (!*args[*cur_arg + 1]) {
8070 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8071 return ERR_ALERT | ERR_FATAL;
8072 }
8073
8074 free(newsrv->ssl_ctx.ciphersuites);
8075 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8076 return 0;
8077}
8078#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008079
Emeric Brunef42d922012-10-11 16:11:36 +02008080/* parse the "crl-file" server keyword */
8081static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8082{
8083#ifndef X509_V_FLAG_CRL_CHECK
8084 if (err)
8085 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8086 return ERR_ALERT | ERR_FATAL;
8087#else
8088 if (!*args[*cur_arg + 1]) {
8089 if (err)
8090 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8091 return ERR_ALERT | ERR_FATAL;
8092 }
8093
Willy Tarreauef934602016-12-22 23:12:01 +01008094 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8095 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008096 else
8097 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8098
8099 return 0;
8100#endif
8101}
8102
Emeric Bruna7aa3092012-10-26 12:58:00 +02008103/* parse the "crt" server keyword */
8104static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8105{
8106 if (!*args[*cur_arg + 1]) {
8107 if (err)
8108 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8109 return ERR_ALERT | ERR_FATAL;
8110 }
8111
Willy Tarreauef934602016-12-22 23:12:01 +01008112 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008113 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008114 else
8115 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8116
8117 return 0;
8118}
Emeric Brunef42d922012-10-11 16:11:36 +02008119
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008120/* parse the "no-check-ssl" server keyword */
8121static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8122{
8123 newsrv->check.use_ssl = 0;
8124 free(newsrv->ssl_ctx.ciphers);
8125 newsrv->ssl_ctx.ciphers = NULL;
8126 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8127 return 0;
8128}
8129
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008130/* parse the "no-send-proxy-v2-ssl" server keyword */
8131static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8132{
8133 newsrv->pp_opts &= ~SRV_PP_V2;
8134 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8135 return 0;
8136}
8137
8138/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8139static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8140{
8141 newsrv->pp_opts &= ~SRV_PP_V2;
8142 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8143 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8144 return 0;
8145}
8146
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008147/* parse the "no-ssl" server keyword */
8148static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8149{
8150 newsrv->use_ssl = 0;
8151 free(newsrv->ssl_ctx.ciphers);
8152 newsrv->ssl_ctx.ciphers = NULL;
8153 return 0;
8154}
8155
Olivier Houchard522eea72017-11-03 16:27:47 +01008156/* parse the "allow-0rtt" server keyword */
8157static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8158{
8159 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8160 return 0;
8161}
8162
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008163/* parse the "no-ssl-reuse" server keyword */
8164static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8165{
8166 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8167 return 0;
8168}
8169
Emeric Brunf9c5c472012-10-11 15:28:34 +02008170/* parse the "no-tls-tickets" server keyword */
8171static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8172{
8173 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8174 return 0;
8175}
David Safb76832014-05-08 23:42:08 -04008176/* parse the "send-proxy-v2-ssl" server keyword */
8177static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8178{
8179 newsrv->pp_opts |= SRV_PP_V2;
8180 newsrv->pp_opts |= SRV_PP_V2_SSL;
8181 return 0;
8182}
8183
8184/* parse the "send-proxy-v2-ssl-cn" server keyword */
8185static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8186{
8187 newsrv->pp_opts |= SRV_PP_V2;
8188 newsrv->pp_opts |= SRV_PP_V2_SSL;
8189 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8190 return 0;
8191}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008192
Willy Tarreau732eac42015-07-09 11:40:25 +02008193/* parse the "sni" server keyword */
8194static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8195{
8196#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8197 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8198 return ERR_ALERT | ERR_FATAL;
8199#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008200 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008201
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008202 arg = args[*cur_arg + 1];
8203 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008204 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8205 return ERR_ALERT | ERR_FATAL;
8206 }
8207
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008208 free(newsrv->sni_expr);
8209 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008210
Willy Tarreau732eac42015-07-09 11:40:25 +02008211 return 0;
8212#endif
8213}
8214
Willy Tarreau92faadf2012-10-10 23:04:25 +02008215/* parse the "ssl" server keyword */
8216static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8217{
8218 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008219 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8220 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008221#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8222 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8223 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8224#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008225 return 0;
8226}
8227
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008228/* parse the "ssl-reuse" server keyword */
8229static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8230{
8231 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8232 return 0;
8233}
8234
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008235/* parse the "tls-tickets" server keyword */
8236static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8237{
8238 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8239 return 0;
8240}
8241
Emeric Brunef42d922012-10-11 16:11:36 +02008242/* parse the "verify" server keyword */
8243static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8244{
8245 if (!*args[*cur_arg + 1]) {
8246 if (err)
8247 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8248 return ERR_ALERT | ERR_FATAL;
8249 }
8250
8251 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008252 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008253 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008254 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008255 else {
8256 if (err)
8257 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8258 args[*cur_arg], args[*cur_arg + 1]);
8259 return ERR_ALERT | ERR_FATAL;
8260 }
8261
Evan Broderbe554312013-06-27 00:05:25 -07008262 return 0;
8263}
8264
8265/* parse the "verifyhost" server keyword */
8266static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8267{
8268 if (!*args[*cur_arg + 1]) {
8269 if (err)
8270 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8271 return ERR_ALERT | ERR_FATAL;
8272 }
8273
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008274 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008275 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8276
Emeric Brunef42d922012-10-11 16:11:36 +02008277 return 0;
8278}
8279
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008280/* parse the "ssl-default-bind-options" keyword in global section */
8281static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8282 struct proxy *defpx, const char *file, int line,
8283 char **err) {
8284 int i = 1;
8285
8286 if (*(args[i]) == 0) {
8287 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8288 return -1;
8289 }
8290 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008291 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008292 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008293 else if (!strcmp(args[i], "prefer-client-ciphers"))
8294 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008295 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8296 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8297 i++;
8298 else {
8299 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8300 return -1;
8301 }
8302 }
8303 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008304 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8305 return -1;
8306 }
8307 i++;
8308 }
8309 return 0;
8310}
8311
8312/* parse the "ssl-default-server-options" keyword in global section */
8313static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8314 struct proxy *defpx, const char *file, int line,
8315 char **err) {
8316 int i = 1;
8317
8318 if (*(args[i]) == 0) {
8319 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8320 return -1;
8321 }
8322 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008323 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008324 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008325 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8326 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8327 i++;
8328 else {
8329 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8330 return -1;
8331 }
8332 }
8333 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008334 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8335 return -1;
8336 }
8337 i++;
8338 }
8339 return 0;
8340}
8341
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008342/* parse the "ca-base" / "crt-base" keywords in global section.
8343 * Returns <0 on alert, >0 on warning, 0 on success.
8344 */
8345static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8346 struct proxy *defpx, const char *file, int line,
8347 char **err)
8348{
8349 char **target;
8350
Willy Tarreauef934602016-12-22 23:12:01 +01008351 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008352
8353 if (too_many_args(1, args, err, NULL))
8354 return -1;
8355
8356 if (*target) {
8357 memprintf(err, "'%s' already specified.", args[0]);
8358 return -1;
8359 }
8360
8361 if (*(args[1]) == 0) {
8362 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8363 return -1;
8364 }
8365 *target = strdup(args[1]);
8366 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008367}
8368
8369/* parse the "ssl-mode-async" keyword in global section.
8370 * Returns <0 on alert, >0 on warning, 0 on success.
8371 */
8372static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8373 struct proxy *defpx, const char *file, int line,
8374 char **err)
8375{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008376#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008377 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008378 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008379 return 0;
8380#else
8381 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8382 return -1;
8383#endif
8384}
8385
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008386#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008387static int ssl_check_async_engine_count(void) {
8388 int err_code = 0;
8389
Emeric Brun3854e012017-05-17 20:42:48 +02008390 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008391 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008392 err_code = ERR_ABORT;
8393 }
8394 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008395}
8396
Grant Zhang872f9c22017-01-21 01:10:18 +00008397/* parse the "ssl-engine" keyword in global section.
8398 * Returns <0 on alert, >0 on warning, 0 on success.
8399 */
8400static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8401 struct proxy *defpx, const char *file, int line,
8402 char **err)
8403{
8404 char *algo;
8405 int ret = -1;
8406
8407 if (*(args[1]) == 0) {
8408 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8409 return ret;
8410 }
8411
8412 if (*(args[2]) == 0) {
8413 /* if no list of algorithms is given, it defaults to ALL */
8414 algo = strdup("ALL");
8415 goto add_engine;
8416 }
8417
8418 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8419 if (strcmp(args[2], "algo") != 0) {
8420 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8421 return ret;
8422 }
8423
8424 if (*(args[3]) == 0) {
8425 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8426 return ret;
8427 }
8428 algo = strdup(args[3]);
8429
8430add_engine:
8431 if (ssl_init_single_engine(args[1], algo)==0) {
8432 openssl_engines_initialized++;
8433 ret = 0;
8434 }
8435 free(algo);
8436 return ret;
8437}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008438#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008439
Willy Tarreauf22e9682016-12-21 23:23:19 +01008440/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8441 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8442 */
8443static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8444 struct proxy *defpx, const char *file, int line,
8445 char **err)
8446{
8447 char **target;
8448
Willy Tarreauef934602016-12-22 23:12:01 +01008449 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008450
8451 if (too_many_args(1, args, err, NULL))
8452 return -1;
8453
8454 if (*(args[1]) == 0) {
8455 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8456 return -1;
8457 }
8458
8459 free(*target);
8460 *target = strdup(args[1]);
8461 return 0;
8462}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008463
8464#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8465/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8466 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8467 */
8468static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8469 struct proxy *defpx, const char *file, int line,
8470 char **err)
8471{
8472 char **target;
8473
8474 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8475
8476 if (too_many_args(1, args, err, NULL))
8477 return -1;
8478
8479 if (*(args[1]) == 0) {
8480 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8481 return -1;
8482 }
8483
8484 free(*target);
8485 *target = strdup(args[1]);
8486 return 0;
8487}
8488#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008489
Willy Tarreau9ceda382016-12-21 23:13:03 +01008490/* parse various global tune.ssl settings consisting in positive integers.
8491 * Returns <0 on alert, >0 on warning, 0 on success.
8492 */
8493static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8494 struct proxy *defpx, const char *file, int line,
8495 char **err)
8496{
8497 int *target;
8498
8499 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8500 target = &global.tune.sslcachesize;
8501 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008502 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008503 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008504 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008505 else if (strcmp(args[0], "maxsslconn") == 0)
8506 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008507 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8508 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008509 else {
8510 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8511 return -1;
8512 }
8513
8514 if (too_many_args(1, args, err, NULL))
8515 return -1;
8516
8517 if (*(args[1]) == 0) {
8518 memprintf(err, "'%s' expects an integer argument.", args[0]);
8519 return -1;
8520 }
8521
8522 *target = atoi(args[1]);
8523 if (*target < 0) {
8524 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8525 return -1;
8526 }
8527 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008528}
8529
8530static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8531 struct proxy *defpx, const char *file, int line,
8532 char **err)
8533{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008534 int ret;
8535
8536 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8537 if (ret != 0)
8538 return ret;
8539
Willy Tarreaubafbe012017-11-24 17:34:44 +01008540 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008541 memprintf(err, "'%s' is already configured.", args[0]);
8542 return -1;
8543 }
8544
Willy Tarreaubafbe012017-11-24 17:34:44 +01008545 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8546 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008547 memprintf(err, "Out of memory error.");
8548 return -1;
8549 }
8550 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008551}
8552
8553/* parse "ssl.force-private-cache".
8554 * Returns <0 on alert, >0 on warning, 0 on success.
8555 */
8556static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8557 struct proxy *defpx, const char *file, int line,
8558 char **err)
8559{
8560 if (too_many_args(0, args, err, NULL))
8561 return -1;
8562
Willy Tarreauef934602016-12-22 23:12:01 +01008563 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008564 return 0;
8565}
8566
8567/* parse "ssl.lifetime".
8568 * Returns <0 on alert, >0 on warning, 0 on success.
8569 */
8570static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8571 struct proxy *defpx, const char *file, int line,
8572 char **err)
8573{
8574 const char *res;
8575
8576 if (too_many_args(1, args, err, NULL))
8577 return -1;
8578
8579 if (*(args[1]) == 0) {
8580 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8581 return -1;
8582 }
8583
Willy Tarreauef934602016-12-22 23:12:01 +01008584 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008585 if (res) {
8586 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8587 return -1;
8588 }
8589 return 0;
8590}
8591
8592#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008593/* parse "ssl-dh-param-file".
8594 * Returns <0 on alert, >0 on warning, 0 on success.
8595 */
8596static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8597 struct proxy *defpx, const char *file, int line,
8598 char **err)
8599{
8600 if (too_many_args(1, args, err, NULL))
8601 return -1;
8602
8603 if (*(args[1]) == 0) {
8604 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8605 return -1;
8606 }
8607
8608 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8609 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8610 return -1;
8611 }
8612 return 0;
8613}
8614
Willy Tarreau9ceda382016-12-21 23:13:03 +01008615/* parse "ssl.default-dh-param".
8616 * Returns <0 on alert, >0 on warning, 0 on success.
8617 */
8618static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8619 struct proxy *defpx, const char *file, int line,
8620 char **err)
8621{
8622 if (too_many_args(1, args, err, NULL))
8623 return -1;
8624
8625 if (*(args[1]) == 0) {
8626 memprintf(err, "'%s' expects an integer argument.", args[0]);
8627 return -1;
8628 }
8629
Willy Tarreauef934602016-12-22 23:12:01 +01008630 global_ssl.default_dh_param = atoi(args[1]);
8631 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008632 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8633 return -1;
8634 }
8635 return 0;
8636}
8637#endif
8638
8639
William Lallemand32af2032016-10-29 18:09:35 +02008640/* This function is used with TLS ticket keys management. It permits to browse
8641 * each reference. The variable <getnext> must contain the current node,
8642 * <end> point to the root node.
8643 */
8644#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8645static inline
8646struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8647{
8648 struct tls_keys_ref *ref = getnext;
8649
8650 while (1) {
8651
8652 /* Get next list entry. */
8653 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8654
8655 /* If the entry is the last of the list, return NULL. */
8656 if (&ref->list == end)
8657 return NULL;
8658
8659 return ref;
8660 }
8661}
8662
8663static inline
8664struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8665{
8666 int id;
8667 char *error;
8668
8669 /* If the reference starts by a '#', this is numeric id. */
8670 if (reference[0] == '#') {
8671 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8672 id = strtol(reference + 1, &error, 10);
8673 if (*error != '\0')
8674 return NULL;
8675
8676 /* Perform the unique id lookup. */
8677 return tlskeys_ref_lookupid(id);
8678 }
8679
8680 /* Perform the string lookup. */
8681 return tlskeys_ref_lookup(reference);
8682}
8683#endif
8684
8685
8686#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8687
8688static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8689
8690static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8691 return cli_io_handler_tlskeys_files(appctx);
8692}
8693
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008694/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8695 * (next index to be dumped), and cli.p0 (next key reference).
8696 */
William Lallemand32af2032016-10-29 18:09:35 +02008697static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8698
8699 struct stream_interface *si = appctx->owner;
8700
8701 switch (appctx->st2) {
8702 case STAT_ST_INIT:
8703 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008704 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008705 * later and restart at the state "STAT_ST_INIT".
8706 */
8707 chunk_reset(&trash);
8708
8709 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8710 chunk_appendf(&trash, "# id secret\n");
8711 else
8712 chunk_appendf(&trash, "# id (file)\n");
8713
Willy Tarreau06d80a92017-10-19 14:32:15 +02008714 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008715 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008716 return 0;
8717 }
8718
William Lallemand32af2032016-10-29 18:09:35 +02008719 /* Now, we start the browsing of the references lists.
8720 * Note that the following call to LIST_ELEM return bad pointer. The only
8721 * available field of this pointer is <list>. It is used with the function
8722 * tlskeys_list_get_next() for retruning the first available entry
8723 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008724 if (appctx->ctx.cli.p0 == NULL) {
8725 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8726 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008727 }
8728
8729 appctx->st2 = STAT_ST_LIST;
8730 /* fall through */
8731
8732 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008733 while (appctx->ctx.cli.p0) {
8734 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008735
8736 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008737 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008738 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008739
8740 if (appctx->ctx.cli.i1 == 0)
8741 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8742
William Lallemand32af2032016-10-29 18:09:35 +02008743 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008744 int head;
8745
8746 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8747 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008748 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008749 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008750
8751 chunk_reset(t2);
8752 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008753 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8754 sizeof(struct tls_sess_key),
8755 t2->area, t2->size);
8756 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8757 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008758
Willy Tarreau06d80a92017-10-19 14:32:15 +02008759 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008760 /* let's try again later from this stream. We add ourselves into
8761 * this stream's users so that it can remove us upon termination.
8762 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008763 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008764 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008765 return 0;
8766 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008767 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008768 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008769 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008770 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008771 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008772 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008773 /* let's try again later from this stream. We add ourselves into
8774 * this stream's users so that it can remove us upon termination.
8775 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008776 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008777 return 0;
8778 }
8779
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008780 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008781 break;
8782
8783 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008784 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008785 }
8786
8787 appctx->st2 = STAT_ST_FIN;
8788 /* fall through */
8789
8790 default:
8791 appctx->st2 = STAT_ST_FIN;
8792 return 1;
8793 }
8794 return 0;
8795}
8796
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008797/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008798static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008799{
William Lallemand32af2032016-10-29 18:09:35 +02008800 /* no parameter, shows only file list */
8801 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008802 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008803 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008804 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008805 }
8806
8807 if (args[2][0] == '*') {
8808 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008809 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008810 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008811 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8812 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008813 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008814 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008815 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008816 return 1;
8817 }
8818 }
William Lallemand32af2032016-10-29 18:09:35 +02008819 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008820 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008821}
8822
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008823static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008824{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008825 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008826 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008827
William Lallemand32af2032016-10-29 18:09:35 +02008828 /* Expect two parameters: the filename and the new new TLS key in encoding */
8829 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008830 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008831 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 +01008832 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008833 return 1;
8834 }
8835
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008836 ref = tlskeys_ref_lookup_ref(args[3]);
8837 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008838 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008839 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008840 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008841 return 1;
8842 }
8843
Willy Tarreau1c913e42018-08-22 05:26:57 +02008844 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8845 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008846 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008847 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008848 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008849 return 1;
8850 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008851 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008852 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008853 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008854 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008855 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008856 return 1;
8857
8858}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008859#endif
William Lallemand32af2032016-10-29 18:09:35 +02008860
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008861static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008862{
8863#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8864 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008865 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008866
8867 if (!payload)
8868 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008869
8870 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008871 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008872 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008873 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008874 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008875 return 1;
8876 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008877
8878 /* remove \r and \n from the payload */
8879 for (i = 0, j = 0; payload[i]; i++) {
8880 if (payload[i] == '\r' || payload[i] == '\n')
8881 continue;
8882 payload[j++] = payload[i];
8883 }
8884 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008885
Willy Tarreau1c913e42018-08-22 05:26:57 +02008886 ret = base64dec(payload, j, trash.area, trash.size);
8887 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008888 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008889 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008890 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008891 return 1;
8892 }
8893
Willy Tarreau1c913e42018-08-22 05:26:57 +02008894 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008895 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8896 if (err) {
8897 memprintf(&err, "%s.\n", err);
8898 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008899 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008900 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008901 else {
8902 appctx->ctx.cli.severity = LOG_ERR;
8903 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8904 appctx->st0 = CLI_ST_PRINT;
8905 }
William Lallemand32af2032016-10-29 18:09:35 +02008906 return 1;
8907 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008908 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008909 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008910 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008911 return 1;
8912#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008913 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008914 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 +01008915 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008916 return 1;
8917#endif
8918
8919}
8920
8921/* register cli keywords */
8922static struct cli_kw_list cli_kws = {{ },{
8923#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8924 { { "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 +02008925 { { "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 +02008926#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008927 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008928 { { NULL }, NULL, NULL, NULL }
8929}};
8930
Willy Tarreau0108d902018-11-25 19:14:37 +01008931INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008932
Willy Tarreau7875d092012-09-10 08:20:03 +02008933/* Note: must not be declared <const> as its list will be overwritten.
8934 * Please take care of keeping this list alphabetically sorted.
8935 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008936static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008937 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008938 { "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 +01008939#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8940 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8941#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008942 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008943#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8944 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8945#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008946 { "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 +02008947 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008948 { "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 +02008949 { "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 -04008950#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008951 { "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 -04008952#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008953#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8954 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8955#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008956 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8957 { "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 +01008958 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008959 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008960 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8961 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8962 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8963 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8964 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8965 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8966 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8967 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008968 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008969 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8970 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008971 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008972 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8973 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8974 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8975 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8976 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8977 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8978 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008979 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008980 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008981 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008982 { "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 +01008983 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008984 { "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 +02008985 { "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 +01008986 { "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 +02008987 { "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 +01008988#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008989 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008990#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008991#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008992 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008993#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008994 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008995#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02008996 { "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 -04008997#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008998 { "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 -04008999#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009000 { "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 -04009001#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009002#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9003 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9004#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009005#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009006 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009007#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009008 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9009 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9010 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9011 { "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 +02009012 { NULL, NULL, 0, 0, 0 },
9013}};
9014
Willy Tarreau0108d902018-11-25 19:14:37 +01009015INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9016
Willy Tarreau7875d092012-09-10 08:20:03 +02009017/* Note: must not be declared <const> as its list will be overwritten.
9018 * Please take care of keeping this list alphabetically sorted.
9019 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009020static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009021 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9022 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009023 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009024}};
9025
Willy Tarreau0108d902018-11-25 19:14:37 +01009026INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9027
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009028/* Note: must not be declared <const> as its list will be overwritten.
9029 * Please take care of keeping this list alphabetically sorted, doing so helps
9030 * all code contributors.
9031 * Optional keywords are also declared with a NULL ->parse() function so that
9032 * the config parser can report an appropriate error when a known keyword was
9033 * not enabled.
9034 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009035static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009036 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009037 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9038 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9039 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009040#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9041 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9042#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009043 { "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 +01009044 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009045 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009046 { "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 +01009047 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009048 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9049 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009050 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9051 { NULL, NULL, 0 },
9052};
9053
Willy Tarreau0108d902018-11-25 19:14:37 +01009054/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9055
Willy Tarreau51fb7652012-09-18 18:24:39 +02009056static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009057 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009058 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9059 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9060 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9061 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9062 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9063 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009064#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9065 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9066#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009067 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9068 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9069 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9070 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9071 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9072 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9073 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9074 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9075 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9076 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009077 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009078 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009079 { "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 +02009080 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9081 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9082 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9083 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009084 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009085 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9086 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009087 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9088 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009089 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9090 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9091 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9092 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9093 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009094 { NULL, NULL, 0 },
9095}};
Emeric Brun46591952012-05-18 15:47:34 +02009096
Willy Tarreau0108d902018-11-25 19:14:37 +01009097INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9098
Willy Tarreau92faadf2012-10-10 23:04:25 +02009099/* Note: must not be declared <const> as its list will be overwritten.
9100 * Please take care of keeping this list alphabetically sorted, doing so helps
9101 * all code contributors.
9102 * Optional keywords are also declared with a NULL ->parse() function so that
9103 * the config parser can report an appropriate error when a known keyword was
9104 * not enabled.
9105 */
9106static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009107 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009108 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009109 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009110 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009111 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9112 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009113#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9114 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9115#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009116 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9117 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9118 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9119 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9120 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9121 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9122 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9123 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9124 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9125 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9126 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9127 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9128 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9129 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9130 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9131 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9132 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9133 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009134 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009135 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9136 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9137 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9138 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9139 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9140 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9141 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9142 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9143 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9144 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009145 { NULL, NULL, 0, 0 },
9146}};
9147
Willy Tarreau0108d902018-11-25 19:14:37 +01009148INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9149
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009150static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009151 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9152 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009153 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009154 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9155 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009156#ifndef OPENSSL_NO_DH
9157 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9158#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009159 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009160#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009161 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009162#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009163 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9164#ifndef OPENSSL_NO_DH
9165 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9166#endif
9167 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9168 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9169 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9170 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009171 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009172 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9173 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009174#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9175 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9176 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9177#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009178 { 0, NULL, NULL },
9179}};
9180
Willy Tarreau0108d902018-11-25 19:14:37 +01009181INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9182
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009183/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009184static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009185 .snd_buf = ssl_sock_from_buf,
9186 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009187 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009188 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009189 .rcv_pipe = NULL,
9190 .snd_pipe = NULL,
9191 .shutr = NULL,
9192 .shutw = ssl_sock_shutw,
9193 .close = ssl_sock_close,
9194 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009195 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009196 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009197 .prepare_srv = ssl_sock_prepare_srv_ctx,
9198 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009199 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009200 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009201};
9202
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009203enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9204 struct session *sess, struct stream *s, int flags)
9205{
9206 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009207 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009208
9209 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009210 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009211
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009212 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009213 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009214 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009215 s->req.flags |= CF_READ_NULL;
9216 return ACT_RET_YIELD;
9217 }
9218 }
9219 return (ACT_RET_CONT);
9220}
9221
9222static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9223{
9224 rule->action_ptr = ssl_action_wait_for_hs;
9225
9226 return ACT_RET_PRS_OK;
9227}
9228
9229static struct action_kw_list http_req_actions = {ILH, {
9230 { "wait-for-handshake", ssl_parse_wait_for_hs },
9231 { /* END */ }
9232}};
9233
Willy Tarreau0108d902018-11-25 19:14:37 +01009234INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9235
Daniel Jakots54ffb912015-11-06 20:02:41 +01009236#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009237
9238static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9239{
9240 if (ptr) {
9241 chunk_destroy(ptr);
9242 free(ptr);
9243 }
9244}
9245
9246#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009247static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9248{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009249 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009250}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009251
Emeric Brun46591952012-05-18 15:47:34 +02009252__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009253static void __ssl_sock_init(void)
9254{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009255 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009256 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009257
Emeric Brun46591952012-05-18 15:47:34 +02009258 STACK_OF(SSL_COMP)* cm;
9259
Willy Tarreauef934602016-12-22 23:12:01 +01009260 if (global_ssl.listen_default_ciphers)
9261 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9262 if (global_ssl.connect_default_ciphers)
9263 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009264#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9265 if (global_ssl.listen_default_ciphersuites)
9266 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9267 if (global_ssl.connect_default_ciphersuites)
9268 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9269#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009270
Willy Tarreau13e14102016-12-22 20:25:26 +01009271 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009272 SSL_library_init();
9273 cm = SSL_COMP_get_compression_methods();
9274 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009275#ifdef USE_THREAD
9276 ssl_locking_init();
9277#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009278#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009279 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9280#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009281 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009282 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 +01009283 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009284#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009285 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009286 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009287#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009288#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9289 hap_register_post_check(tlskeys_finalize_config);
9290#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009291
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009292 ptr = NULL;
9293 memprintf(&ptr, "Built with OpenSSL version : "
9294#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009295 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009296#else /* OPENSSL_IS_BORINGSSL */
9297 OPENSSL_VERSION_TEXT
9298 "\nRunning on OpenSSL version : %s%s",
9299 SSLeay_version(SSLEAY_VERSION),
9300 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9301#endif
9302 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9303#if OPENSSL_VERSION_NUMBER < 0x00907000L
9304 "no (library version too old)"
9305#elif defined(OPENSSL_NO_TLSEXT)
9306 "no (disabled via OPENSSL_NO_TLSEXT)"
9307#else
9308 "yes"
9309#endif
9310 "", ptr);
9311
9312 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9313#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9314 "yes"
9315#else
9316#ifdef OPENSSL_NO_TLSEXT
9317 "no (because of OPENSSL_NO_TLSEXT)"
9318#else
9319 "no (version might be too old, 0.9.8f min needed)"
9320#endif
9321#endif
9322 "", ptr);
9323
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009324 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9325 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9326 if (methodVersions[i].option)
9327 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009328
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009329 hap_register_build_opts(ptr, 1);
9330
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009331 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9332 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02009333
9334#ifndef OPENSSL_NO_DH
9335 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00009336 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009337#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009338#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009339 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009340#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02009341 /* Load SSL string for the verbose & debug mode. */
9342 ERR_load_SSL_strings();
Emeric Brun46591952012-05-18 15:47:34 +02009343}
9344
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009345#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009346void ssl_free_engines(void) {
9347 struct ssl_engine_list *wl, *wlb;
9348 /* free up engine list */
9349 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9350 ENGINE_finish(wl->e);
9351 ENGINE_free(wl->e);
9352 LIST_DEL(&wl->list);
9353 free(wl);
9354 }
9355}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009356#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009357
Remi Gacogned3a23c32015-05-28 16:39:47 +02009358#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009359void ssl_free_dh(void) {
9360 if (local_dh_1024) {
9361 DH_free(local_dh_1024);
9362 local_dh_1024 = NULL;
9363 }
9364 if (local_dh_2048) {
9365 DH_free(local_dh_2048);
9366 local_dh_2048 = NULL;
9367 }
9368 if (local_dh_4096) {
9369 DH_free(local_dh_4096);
9370 local_dh_4096 = NULL;
9371 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009372 if (global_dh) {
9373 DH_free(global_dh);
9374 global_dh = NULL;
9375 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009376}
9377#endif
9378
9379__attribute__((destructor))
9380static void __ssl_sock_deinit(void)
9381{
9382#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009383 if (ssl_ctx_lru_tree) {
9384 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009385 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009386 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009387#endif
9388
9389 ERR_remove_state(0);
9390 ERR_free_strings();
9391
9392 EVP_cleanup();
9393
9394#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9395 CRYPTO_cleanup_all_ex_data();
9396#endif
9397}
9398
9399
Emeric Brun46591952012-05-18 15:47:34 +02009400/*
9401 * Local variables:
9402 * c-indent-level: 8
9403 * c-basic-offset: 8
9404 * End:
9405 */