blob: 5fd4f4e9e3e73a5e7cf7b7f20d1960d42afb369d [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020046#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010047#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020048#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000056#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020057#endif
Emeric Brun46591952012-05-18 15:47:34 +020058
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020059#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000060#include <openssl/async.h>
61#endif
62
Christopher Faulet31af49d2015-06-09 17:29:50 +020063#include <import/lru.h>
64#include <import/xxhash.h>
65
Emeric Brun46591952012-05-18 15:47:34 +020066#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020067#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020068#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010072#include <common/initcall.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <common/standard.h>
74#include <common/ticks.h>
75#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010076#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010077#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020078
Emeric Brunfc0421f2012-09-07 17:30:07 +020079#include <ebsttree.h>
80
William Lallemand32af2032016-10-29 18:09:35 +020081#include <types/applet.h>
82#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#include <types/global.h>
84#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020085#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020086
Willy Tarreau7875d092012-09-10 08:20:03 +020087#include <proto/acl.h>
88#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020089#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020090#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020091#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020092#include <proto/fd.h>
93#include <proto/freq_ctr.h>
94#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020095#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020096#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020097#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010098#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020099#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +0200100#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +0200101#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200102#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200103#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200104#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200105#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200107#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200108#include <proto/task.h>
109
Willy Tarreau518cedd2014-02-17 15:43:01 +0100110/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200111#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100112#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100113#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200114#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
115
Emeric Brunf282a812012-09-21 15:27:54 +0200116/* bits 0xFFFF0000 are reserved to store verify errors */
117
118/* Verify errors macros */
119#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
120#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
121#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
122
123#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
124#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
125#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200126
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100127/* Supported hash function for TLS tickets */
128#ifdef OPENSSL_NO_SHA256
129#define HASH_FUNCT EVP_sha1
130#else
131#define HASH_FUNCT EVP_sha256
132#endif /* OPENSSL_NO_SHA256 */
133
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200134/* ssl_methods flags for ssl options */
135#define MC_SSL_O_ALL 0x0000
136#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
137#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
138#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
139#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200140#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200141
142/* ssl_methods versions */
143enum {
144 CONF_TLSV_NONE = 0,
145 CONF_TLSV_MIN = 1,
146 CONF_SSLV3 = 1,
147 CONF_TLSV10 = 2,
148 CONF_TLSV11 = 3,
149 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200150 CONF_TLSV13 = 5,
151 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200152};
153
Emeric Brun850efd52014-01-29 12:24:34 +0100154/* server and bind verify method, it uses a global value as default */
155enum {
156 SSL_SOCK_VERIFY_DEFAULT = 0,
157 SSL_SOCK_VERIFY_REQUIRED = 1,
158 SSL_SOCK_VERIFY_OPTIONAL = 2,
159 SSL_SOCK_VERIFY_NONE = 3,
160};
161
William Lallemand3f85c9a2017-10-09 16:30:50 +0200162
Willy Tarreau71b734c2014-01-28 15:19:44 +0100163int sslconns = 0;
164int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100165static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100166int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200167
Willy Tarreauef934602016-12-22 23:12:01 +0100168static struct {
169 char *crt_base; /* base directory path for certificates */
170 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000171 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100172
173 char *listen_default_ciphers;
174 char *connect_default_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200175#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
176 char *listen_default_ciphersuites;
177 char *connect_default_ciphersuites;
178#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100179 int listen_default_ssloptions;
180 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200181 struct tls_version_filter listen_default_sslmethods;
182 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100183
184 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
185 unsigned int life_time; /* SSL session lifetime in seconds */
186 unsigned int max_record; /* SSL max record size */
187 unsigned int default_dh_param; /* SSL maximum DH parameter size */
188 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100189 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100190} global_ssl = {
191#ifdef LISTEN_DEFAULT_CIPHERS
192 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
193#endif
194#ifdef CONNECT_DEFAULT_CIPHERS
195 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
196#endif
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200197#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
198#ifdef LISTEN_DEFAULT_CIPHERSUITES
199 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
200#endif
201#ifdef CONNECT_DEFAULT_CIPHERSUITES
202 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
203#endif
204#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100205 .listen_default_ssloptions = BC_SSL_O_NONE,
206 .connect_default_ssloptions = SRV_SSL_O_NONE,
207
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200208 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
209 .listen_default_sslmethods.min = CONF_TLSV_NONE,
210 .listen_default_sslmethods.max = CONF_TLSV_NONE,
211 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
212 .connect_default_sslmethods.min = CONF_TLSV_NONE,
213 .connect_default_sslmethods.max = CONF_TLSV_NONE,
214
Willy Tarreauef934602016-12-22 23:12:01 +0100215#ifdef DEFAULT_SSL_MAX_RECORD
216 .max_record = DEFAULT_SSL_MAX_RECORD,
217#endif
218 .default_dh_param = SSL_DEFAULT_DH_PARAM,
219 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100220 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100221};
222
Emeric Brun821bb9b2017-06-15 16:37:39 +0200223#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100224
Emeric Brun821bb9b2017-06-15 16:37:39 +0200225static HA_RWLOCK_T *ssl_rwlocks;
226
227
228unsigned long ssl_id_function(void)
229{
230 return (unsigned long)tid;
231}
232
233void ssl_locking_function(int mode, int n, const char * file, int line)
234{
235 if (mode & CRYPTO_LOCK) {
236 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100237 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200238 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100239 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200240 }
241 else {
242 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100243 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200244 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100245 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200246 }
247}
248
249static int ssl_locking_init(void)
250{
251 int i;
252
253 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
254 if (!ssl_rwlocks)
255 return -1;
256
257 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100258 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200259
260 CRYPTO_set_id_callback(ssl_id_function);
261 CRYPTO_set_locking_callback(ssl_locking_function);
262
263 return 0;
264}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100265
Emeric Brun821bb9b2017-06-15 16:37:39 +0200266#endif
267
268
269
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100270/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100271struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100272 unsigned long long int xxh64;
273 unsigned char ciphersuite_len;
274 char ciphersuite[0];
275};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100276struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100277static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200278static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100279
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100280static int ssl_pkey_info_index = -1;
281
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200282#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
283struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
284#endif
285
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200286#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000287static unsigned int openssl_engines_initialized;
288struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
289struct ssl_engine_list {
290 struct list list;
291 ENGINE *e;
292};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200293#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000294
Remi Gacogne8de54152014-07-15 11:36:40 +0200295#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200296static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200297static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200298static DH *local_dh_1024 = NULL;
299static DH *local_dh_2048 = NULL;
300static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100301static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200302#endif /* OPENSSL_NO_DH */
303
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100304#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200305/* X509V3 Extensions that will be added on generated certificates */
306#define X509V3_EXT_SIZE 5
307static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
308 "basicConstraints",
309 "nsComment",
310 "subjectKeyIdentifier",
311 "authorityKeyIdentifier",
312 "keyUsage",
313};
314static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
315 "CA:FALSE",
316 "\"OpenSSL Generated Certificate\"",
317 "hash",
318 "keyid,issuer:always",
319 "nonRepudiation,digitalSignature,keyEncipherment"
320};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200321/* LRU cache to store generated certificate */
322static struct lru64_head *ssl_ctx_lru_tree = NULL;
323static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200324static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100325__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200327#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
328
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100329static struct ssl_bind_kw ssl_bind_kws[];
330
yanbzhube2774d2015-12-10 15:07:30 -0500331#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
332/* The order here matters for picking a default context,
333 * keep the most common keytype at the bottom of the list
334 */
335const char *SSL_SOCK_KEYTYPE_NAMES[] = {
336 "dsa",
337 "ecdsa",
338 "rsa"
339};
340#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100341#else
342#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500343#endif
344
William Lallemandc3cd35f2017-11-28 11:04:43 +0100345static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100346static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
347
348#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
349
350#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
351 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
352
353#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
354 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200355
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100356/*
357 * This function gives the detail of the SSL error. It is used only
358 * if the debug mode and the verbose mode are activated. It dump all
359 * the SSL error until the stack was empty.
360 */
361static forceinline void ssl_sock_dump_errors(struct connection *conn)
362{
363 unsigned long ret;
364
365 if (unlikely(global.mode & MODE_DEBUG)) {
366 while(1) {
367 ret = ERR_get_error();
368 if (ret == 0)
369 return;
370 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200371 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100372 ERR_func_error_string(ret), ERR_reason_error_string(ret));
373 }
374 }
375}
376
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200377#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500378/*
379 * struct alignment works here such that the key.key is the same as key_data
380 * Do not change the placement of key_data
381 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200382struct certificate_ocsp {
383 struct ebmb_node key;
384 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200385 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200386 long expire;
387};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200388
yanbzhube2774d2015-12-10 15:07:30 -0500389struct ocsp_cbk_arg {
390 int is_single;
391 int single_kt;
392 union {
393 struct certificate_ocsp *s_ocsp;
394 /*
395 * m_ocsp will have multiple entries dependent on key type
396 * Entry 0 - DSA
397 * Entry 1 - ECDSA
398 * Entry 2 - RSA
399 */
400 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
401 };
402};
403
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200404#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000405static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
406{
407 int err_code = ERR_ABORT;
408 ENGINE *engine;
409 struct ssl_engine_list *el;
410
411 /* grab the structural reference to the engine */
412 engine = ENGINE_by_id(engine_id);
413 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100414 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000415 goto fail_get;
416 }
417
418 if (!ENGINE_init(engine)) {
419 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100420 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000421 goto fail_init;
422 }
423
424 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100425 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000426 goto fail_set_method;
427 }
428
429 el = calloc(1, sizeof(*el));
430 el->e = engine;
431 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100432 nb_engines++;
433 if (global_ssl.async)
434 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000435 return 0;
436
437fail_set_method:
438 /* release the functional reference from ENGINE_init() */
439 ENGINE_finish(engine);
440
441fail_init:
442 /* release the structural reference from ENGINE_by_id() */
443 ENGINE_free(engine);
444
445fail_get:
446 return err_code;
447}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200448#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000449
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200450#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200451/*
452 * openssl async fd handler
453 */
454static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000455{
456 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000457
Emeric Brun3854e012017-05-17 20:42:48 +0200458 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000459 * to poll this fd until it is requested
460 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000461 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000462 fd_cant_recv(fd);
463
464 /* crypto engine is available, let's notify the associated
465 * connection that it can pursue its processing.
466 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000467 __conn_sock_want_recv(conn);
468 __conn_sock_want_send(conn);
469 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000470}
471
Emeric Brun3854e012017-05-17 20:42:48 +0200472/*
473 * openssl async delayed SSL_free handler
474 */
475static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000476{
477 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200478 OSSL_ASYNC_FD all_fd[32];
479 size_t num_all_fds = 0;
480 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000481
Emeric Brun3854e012017-05-17 20:42:48 +0200482 /* We suppose that the async job for a same SSL *
483 * are serialized. So if we are awake it is
484 * because the running job has just finished
485 * and we can remove all async fds safely
486 */
487 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
488 if (num_all_fds > 32) {
489 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
490 return;
491 }
492
493 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
494 for (i=0 ; i < num_all_fds ; i++)
495 fd_remove(all_fd[i]);
496
497 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000498 SSL_free(ssl);
Emeric Brun7ad43e72018-10-10 14:51:02 +0200499 HA_ATOMIC_SUB(&sslconns, 1);
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200500 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000501}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000502/*
Emeric Brun3854e012017-05-17 20:42:48 +0200503 * function used to manage a returned SSL_ERROR_WANT_ASYNC
504 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000505 */
Emeric Brun3854e012017-05-17 20:42:48 +0200506static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000507{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100508 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200509 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000510 size_t num_add_fds = 0;
511 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200512 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000513
514 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
515 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200516 if (num_add_fds > 32 || num_del_fds > 32) {
517 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000518 return;
519 }
520
Emeric Brun3854e012017-05-17 20:42:48 +0200521 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000522
Emeric Brun3854e012017-05-17 20:42:48 +0200523 /* We remove unused fds from the fdtab */
524 for (i=0 ; i < num_del_fds ; i++)
525 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000526
Emeric Brun3854e012017-05-17 20:42:48 +0200527 /* We add new fds to the fdtab */
528 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100529 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530 }
531
Emeric Brun3854e012017-05-17 20:42:48 +0200532 num_add_fds = 0;
533 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
534 if (num_add_fds > 32) {
535 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
536 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000537 }
Emeric Brun3854e012017-05-17 20:42:48 +0200538
539 /* We activate the polling for all known async fds */
540 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000541 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200542 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000543 /* To ensure that the fd cache won't be used
544 * We'll prefer to catch a real RD event
545 * because handling an EAGAIN on this fd will
546 * result in a context switch and also
547 * some engines uses a fd in blocking mode.
548 */
549 fd_cant_recv(add_fd[i]);
550 }
Emeric Brun3854e012017-05-17 20:42:48 +0200551
552 /* We must also prevent the conn_handler
553 * to be called until a read event was
554 * polled on an async fd
555 */
556 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000557}
558#endif
559
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200560/*
561 * This function returns the number of seconds elapsed
562 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
563 * date presented un ASN1_GENERALIZEDTIME.
564 *
565 * In parsing error case, it returns -1.
566 */
567static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
568{
569 long epoch;
570 char *p, *end;
571 const unsigned short month_offset[12] = {
572 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
573 };
574 int year, month;
575
576 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
577
578 p = (char *)d->data;
579 end = p + d->length;
580
581 if (end - p < 4) return -1;
582 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
583 p += 4;
584 if (end - p < 2) return -1;
585 month = 10 * (p[0] - '0') + p[1] - '0';
586 if (month < 1 || month > 12) return -1;
587 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
588 We consider leap years and the current month (<marsh or not) */
589 epoch = ( ((year - 1970) * 365)
590 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
591 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
592 + month_offset[month-1]
593 ) * 24 * 60 * 60;
594 p += 2;
595 if (end - p < 2) return -1;
596 /* Add the number of seconds of completed days of current month */
597 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
598 p += 2;
599 if (end - p < 2) return -1;
600 /* Add the completed hours of the current day */
601 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
602 p += 2;
603 if (end - p < 2) return -1;
604 /* Add the completed minutes of the current hour */
605 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
606 p += 2;
607 if (p == end) return -1;
608 /* Test if there is available seconds */
609 if (p[0] < '0' || p[0] > '9')
610 goto nosec;
611 if (end - p < 2) return -1;
612 /* Add the seconds of the current minute */
613 epoch += 10 * (p[0] - '0') + p[1] - '0';
614 p += 2;
615 if (p == end) return -1;
616 /* Ignore seconds float part if present */
617 if (p[0] == '.') {
618 do {
619 if (++p == end) return -1;
620 } while (p[0] >= '0' && p[0] <= '9');
621 }
622
623nosec:
624 if (p[0] == 'Z') {
625 if (end - p != 1) return -1;
626 return epoch;
627 }
628 else if (p[0] == '+') {
629 if (end - p != 5) return -1;
630 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700631 return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200632 }
633 else if (p[0] == '-') {
634 if (end - p != 5) return -1;
635 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700636 return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200637 }
638
639 return -1;
640}
641
Emeric Brun1d3865b2014-06-20 15:37:32 +0200642static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200643
644/* This function starts to check if the OCSP response (in DER format) contained
645 * in chunk 'ocsp_response' is valid (else exits on error).
646 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
647 * contained in the OCSP Response and exits on error if no match.
648 * If it's a valid OCSP Response:
649 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
650 * pointed by 'ocsp'.
651 * If 'ocsp' is NULL, the function looks up into the OCSP response's
652 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
653 * from the response) and exits on error if not found. Finally, If an OCSP response is
654 * already present in the container, it will be overwritten.
655 *
656 * Note: OCSP response containing more than one OCSP Single response is not
657 * considered valid.
658 *
659 * Returns 0 on success, 1 in error case.
660 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200661static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
662 struct certificate_ocsp *ocsp,
663 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200664{
665 OCSP_RESPONSE *resp;
666 OCSP_BASICRESP *bs = NULL;
667 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200668 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200669 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200670 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200671 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200672 int reason;
673 int ret = 1;
674
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200675 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
676 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200677 if (!resp) {
678 memprintf(err, "Unable to parse OCSP response");
679 goto out;
680 }
681
682 rc = OCSP_response_status(resp);
683 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
684 memprintf(err, "OCSP response status not successful");
685 goto out;
686 }
687
688 bs = OCSP_response_get1_basic(resp);
689 if (!bs) {
690 memprintf(err, "Failed to get basic response from OCSP Response");
691 goto out;
692 }
693
694 count_sr = OCSP_resp_count(bs);
695 if (count_sr > 1) {
696 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
697 goto out;
698 }
699
700 sr = OCSP_resp_get0(bs, 0);
701 if (!sr) {
702 memprintf(err, "Failed to get OCSP single response");
703 goto out;
704 }
705
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200706 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
707
Emeric Brun4147b2e2014-06-16 18:36:30 +0200708 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200709 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200710 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200711 goto out;
712 }
713
Emeric Brun13a6b482014-06-20 15:44:34 +0200714 if (!nextupd) {
715 memprintf(err, "OCSP single response: missing nextupdate");
716 goto out;
717 }
718
Emeric Brunc8b27b62014-06-19 14:16:17 +0200719 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200720 if (!rc) {
721 memprintf(err, "OCSP single response: no longer valid.");
722 goto out;
723 }
724
725 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200726 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200727 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
728 goto out;
729 }
730 }
731
732 if (!ocsp) {
733 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
734 unsigned char *p;
735
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200736 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200737 if (!rc) {
738 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
739 goto out;
740 }
741
742 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
743 memprintf(err, "OCSP single response: Certificate ID too long");
744 goto out;
745 }
746
747 p = key;
748 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200749 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200750 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
751 if (!ocsp) {
752 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
753 goto out;
754 }
755 }
756
757 /* According to comments on "chunk_dup", the
758 previous chunk buffer will be freed */
759 if (!chunk_dup(&ocsp->response, ocsp_response)) {
760 memprintf(err, "OCSP response: Memory allocation error");
761 goto out;
762 }
763
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200764 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
765
Emeric Brun4147b2e2014-06-16 18:36:30 +0200766 ret = 0;
767out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100768 ERR_clear_error();
769
Emeric Brun4147b2e2014-06-16 18:36:30 +0200770 if (bs)
771 OCSP_BASICRESP_free(bs);
772
773 if (resp)
774 OCSP_RESPONSE_free(resp);
775
776 return ret;
777}
778/*
779 * External function use to update the OCSP response in the OCSP response's
780 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
781 * to update in DER format.
782 *
783 * Returns 0 on success, 1 in error case.
784 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200785int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200786{
787 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
788}
789
790/*
791 * This function load the OCSP Resonse in DER format contained in file at
792 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
793 *
794 * Returns 0 on success, 1 in error case.
795 */
796static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
797{
798 int fd = -1;
799 int r = 0;
800 int ret = 1;
801
802 fd = open(ocsp_path, O_RDONLY);
803 if (fd == -1) {
804 memprintf(err, "Error opening OCSP response file");
805 goto end;
806 }
807
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200808 trash.data = 0;
809 while (trash.data < trash.size) {
810 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200811 if (r < 0) {
812 if (errno == EINTR)
813 continue;
814
815 memprintf(err, "Error reading OCSP response from file");
816 goto end;
817 }
818 else if (r == 0) {
819 break;
820 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200821 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200822 }
823
824 close(fd);
825 fd = -1;
826
827 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
828end:
829 if (fd != -1)
830 close(fd);
831
832 return ret;
833}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100834#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200835
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100836#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
837static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc)
838{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100839 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100840 struct tls_sess_key *keys;
841 struct connection *conn;
842 int head;
843 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100844 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100845
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200846 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200847 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100848 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
849
850 keys = ref->tlskeys;
851 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100852
853 if (enc) {
854 memcpy(key_name, keys[head].name, 16);
855
856 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100857 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100858
859 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100860 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100861
862 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100863 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100864 } else {
865 for (i = 0; i < TLS_TICKETS_NO; i++) {
866 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
867 goto found;
868 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100869 ret = 0;
870 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100871
Christopher Faulet16f45c82018-02-16 11:23:49 +0100872 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100873 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
874 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100875 goto end;
876
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100877 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100878 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100879 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100880 end:
881 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
882 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200883}
884
885struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
886{
887 struct tls_keys_ref *ref;
888
889 list_for_each_entry(ref, &tlskeys_reference, list)
890 if (ref->filename && strcmp(filename, ref->filename) == 0)
891 return ref;
892 return NULL;
893}
894
895struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
896{
897 struct tls_keys_ref *ref;
898
899 list_for_each_entry(ref, &tlskeys_reference, list)
900 if (ref->unique_id == unique_id)
901 return ref;
902 return NULL;
903}
904
Willy Tarreau83061a82018-07-13 11:56:34 +0200905void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
906 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100907{
908 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200909 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
910 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100911 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
912 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
913}
914
Willy Tarreau83061a82018-07-13 11:56:34 +0200915int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100916{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200917 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
918
919 if(!ref) {
920 memprintf(err, "Unable to locate the referenced filename: %s", filename);
921 return 1;
922 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100923 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200924 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100925}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200926
927/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100928 * automatic ids. It's called just after the basic checks. It returns
929 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200930 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100931static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200932{
933 int i = 0;
934 struct tls_keys_ref *ref, *ref2, *ref3;
935 struct list tkr = LIST_HEAD_INIT(tkr);
936
937 list_for_each_entry(ref, &tlskeys_reference, list) {
938 if (ref->unique_id == -1) {
939 /* Look for the first free id. */
940 while (1) {
941 list_for_each_entry(ref2, &tlskeys_reference, list) {
942 if (ref2->unique_id == i) {
943 i++;
944 break;
945 }
946 }
947 if (&ref2->list == &tlskeys_reference)
948 break;
949 }
950
951 /* Uses the unique id and increment it for the next entry. */
952 ref->unique_id = i;
953 i++;
954 }
955 }
956
957 /* This sort the reference list by id. */
958 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
959 LIST_DEL(&ref->list);
960 list_for_each_entry(ref3, &tkr, list) {
961 if (ref->unique_id < ref3->unique_id) {
962 LIST_ADDQ(&ref3->list, &ref->list);
963 break;
964 }
965 }
966 if (&ref3->list == &tkr)
967 LIST_ADDQ(&tkr, &ref->list);
968 }
969
970 /* swap root */
971 LIST_ADD(&tkr, &tlskeys_reference);
972 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100973 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200974}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
976
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100977#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500978int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
979{
980 switch (evp_keytype) {
981 case EVP_PKEY_RSA:
982 return 2;
983 case EVP_PKEY_DSA:
984 return 0;
985 case EVP_PKEY_EC:
986 return 1;
987 }
988
989 return -1;
990}
991
Emeric Brun4147b2e2014-06-16 18:36:30 +0200992/*
993 * Callback used to set OCSP status extension content in server hello.
994 */
995int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
996{
yanbzhube2774d2015-12-10 15:07:30 -0500997 struct certificate_ocsp *ocsp;
998 struct ocsp_cbk_arg *ocsp_arg;
999 char *ssl_buf;
1000 EVP_PKEY *ssl_pkey;
1001 int key_type;
1002 int index;
1003
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001004 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001005
1006 ssl_pkey = SSL_get_privatekey(ssl);
1007 if (!ssl_pkey)
1008 return SSL_TLSEXT_ERR_NOACK;
1009
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001010 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001011
1012 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1013 ocsp = ocsp_arg->s_ocsp;
1014 else {
1015 /* For multiple certs per context, we have to find the correct OCSP response based on
1016 * the certificate type
1017 */
1018 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1019
1020 if (index < 0)
1021 return SSL_TLSEXT_ERR_NOACK;
1022
1023 ocsp = ocsp_arg->m_ocsp[index];
1024
1025 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001026
1027 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001028 !ocsp->response.area ||
1029 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001030 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001031 return SSL_TLSEXT_ERR_NOACK;
1032
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001033 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001034 if (!ssl_buf)
1035 return SSL_TLSEXT_ERR_NOACK;
1036
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001037 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1038 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001039
1040 return SSL_TLSEXT_ERR_OK;
1041}
1042
1043/*
1044 * This function enables the handling of OCSP status extension on 'ctx' if a
1045 * file name 'cert_path' suffixed using ".ocsp" is present.
1046 * To enable OCSP status extension, the issuer's certificate is mandatory.
1047 * It should be present in the certificate's extra chain builded from file
1048 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1049 * named 'cert_path' suffixed using '.issuer'.
1050 *
1051 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1052 * response. If file is empty or content is not a valid OCSP response,
1053 * OCSP status extension is enabled but OCSP response is ignored (a warning
1054 * is displayed).
1055 *
1056 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001057 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001058 */
1059static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1060{
1061
1062 BIO *in = NULL;
1063 X509 *x, *xi = NULL, *issuer = NULL;
1064 STACK_OF(X509) *chain = NULL;
1065 OCSP_CERTID *cid = NULL;
1066 SSL *ssl;
1067 char ocsp_path[MAXPATHLEN+1];
1068 int i, ret = -1;
1069 struct stat st;
1070 struct certificate_ocsp *ocsp = NULL, *iocsp;
1071 char *warn = NULL;
1072 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001073 pem_password_cb *passwd_cb;
1074 void *passwd_cb_userdata;
1075 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001076
1077 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1078
1079 if (stat(ocsp_path, &st))
1080 return 1;
1081
1082 ssl = SSL_new(ctx);
1083 if (!ssl)
1084 goto out;
1085
1086 x = SSL_get_certificate(ssl);
1087 if (!x)
1088 goto out;
1089
1090 /* Try to lookup for issuer in certificate extra chain */
1091#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1092 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1093#else
1094 chain = ctx->extra_certs;
1095#endif
1096 for (i = 0; i < sk_X509_num(chain); i++) {
1097 issuer = sk_X509_value(chain, i);
1098 if (X509_check_issued(issuer, x) == X509_V_OK)
1099 break;
1100 else
1101 issuer = NULL;
1102 }
1103
1104 /* If not found try to load issuer from a suffixed file */
1105 if (!issuer) {
1106 char issuer_path[MAXPATHLEN+1];
1107
1108 in = BIO_new(BIO_s_file());
1109 if (!in)
1110 goto out;
1111
1112 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1113 if (BIO_read_filename(in, issuer_path) <= 0)
1114 goto out;
1115
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001116 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1117 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1118
1119 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001120 if (!xi)
1121 goto out;
1122
1123 if (X509_check_issued(xi, x) != X509_V_OK)
1124 goto out;
1125
1126 issuer = xi;
1127 }
1128
1129 cid = OCSP_cert_to_id(0, x, issuer);
1130 if (!cid)
1131 goto out;
1132
1133 i = i2d_OCSP_CERTID(cid, NULL);
1134 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1135 goto out;
1136
Vincent Bernat02779b62016-04-03 13:48:43 +02001137 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001138 if (!ocsp)
1139 goto out;
1140
1141 p = ocsp->key_data;
1142 i2d_OCSP_CERTID(cid, &p);
1143
1144 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1145 if (iocsp == ocsp)
1146 ocsp = NULL;
1147
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001148#ifndef SSL_CTX_get_tlsext_status_cb
1149# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1150 *cb = (void (*) (void))ctx->tlsext_status_cb;
1151#endif
1152 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1153
1154 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001155 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001156 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001157
1158 cb_arg->is_single = 1;
1159 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001160
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001161 pkey = X509_get_pubkey(x);
1162 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1163 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001164
1165 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1166 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1167 } else {
1168 /*
1169 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1170 * Update that cb_arg with the new cert's staple
1171 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001172 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001173 struct certificate_ocsp *tmp_ocsp;
1174 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001175 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001176 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001177
1178#ifdef SSL_CTX_get_tlsext_status_arg
1179 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1180#else
1181 cb_arg = ctx->tlsext_status_arg;
1182#endif
yanbzhube2774d2015-12-10 15:07:30 -05001183
1184 /*
1185 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1186 * the order of operations below matter, take care when changing it
1187 */
1188 tmp_ocsp = cb_arg->s_ocsp;
1189 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1190 cb_arg->s_ocsp = NULL;
1191 cb_arg->m_ocsp[index] = tmp_ocsp;
1192 cb_arg->is_single = 0;
1193 cb_arg->single_kt = 0;
1194
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001195 pkey = X509_get_pubkey(x);
1196 key_type = EVP_PKEY_base_id(pkey);
1197 EVP_PKEY_free(pkey);
1198
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001199 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001200 if (index >= 0 && !cb_arg->m_ocsp[index])
1201 cb_arg->m_ocsp[index] = iocsp;
1202
1203 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001204
1205 ret = 0;
1206
1207 warn = NULL;
1208 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1209 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001210 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001211 }
1212
1213out:
1214 if (ssl)
1215 SSL_free(ssl);
1216
1217 if (in)
1218 BIO_free(in);
1219
1220 if (xi)
1221 X509_free(xi);
1222
1223 if (cid)
1224 OCSP_CERTID_free(cid);
1225
1226 if (ocsp)
1227 free(ocsp);
1228
1229 if (warn)
1230 free(warn);
1231
1232
1233 return ret;
1234}
1235
1236#endif
1237
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001238#ifdef OPENSSL_IS_BORINGSSL
1239static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1240{
1241 char ocsp_path[MAXPATHLEN+1];
1242 struct stat st;
1243 int fd = -1, r = 0;
1244
1245 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1246 if (stat(ocsp_path, &st))
1247 return 0;
1248
1249 fd = open(ocsp_path, O_RDONLY);
1250 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001251 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001252 return -1;
1253 }
1254
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001255 trash.data = 0;
1256 while (trash.data < trash.size) {
1257 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001258 if (r < 0) {
1259 if (errno == EINTR)
1260 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001261 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001262 close(fd);
1263 return -1;
1264 }
1265 else if (r == 0) {
1266 break;
1267 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001268 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001269 }
1270 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001271 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1272 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001273}
1274#endif
1275
Daniel Jakots54ffb912015-11-06 20:02:41 +01001276#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001277
1278#define CT_EXTENSION_TYPE 18
1279
1280static int sctl_ex_index = -1;
1281
1282/*
1283 * Try to parse Signed Certificate Timestamp List structure. This function
1284 * makes only basic test if the data seems like SCTL. No signature validation
1285 * is performed.
1286 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001287static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001288{
1289 int ret = 1;
1290 int len, pos, sct_len;
1291 unsigned char *data;
1292
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001293 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001294 goto out;
1295
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001296 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001297 len = (data[0] << 8) | data[1];
1298
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001299 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001300 goto out;
1301
1302 data = data + 2;
1303 pos = 0;
1304 while (pos < len) {
1305 if (len - pos < 2)
1306 goto out;
1307
1308 sct_len = (data[pos] << 8) | data[pos + 1];
1309 if (pos + sct_len + 2 > len)
1310 goto out;
1311
1312 pos += sct_len + 2;
1313 }
1314
1315 ret = 0;
1316
1317out:
1318 return ret;
1319}
1320
Willy Tarreau83061a82018-07-13 11:56:34 +02001321static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1322 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001323{
1324 int fd = -1;
1325 int r = 0;
1326 int ret = 1;
1327
1328 *sctl = NULL;
1329
1330 fd = open(sctl_path, O_RDONLY);
1331 if (fd == -1)
1332 goto end;
1333
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001334 trash.data = 0;
1335 while (trash.data < trash.size) {
1336 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001337 if (r < 0) {
1338 if (errno == EINTR)
1339 continue;
1340
1341 goto end;
1342 }
1343 else if (r == 0) {
1344 break;
1345 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001346 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001347 }
1348
1349 ret = ssl_sock_parse_sctl(&trash);
1350 if (ret)
1351 goto end;
1352
Vincent Bernat02779b62016-04-03 13:48:43 +02001353 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001354 if (!chunk_dup(*sctl, &trash)) {
1355 free(*sctl);
1356 *sctl = NULL;
1357 goto end;
1358 }
1359
1360end:
1361 if (fd != -1)
1362 close(fd);
1363
1364 return ret;
1365}
1366
1367int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1368{
Willy Tarreau83061a82018-07-13 11:56:34 +02001369 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001370
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001371 *out = (unsigned char *) sctl->area;
1372 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001373
1374 return 1;
1375}
1376
1377int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1378{
1379 return 1;
1380}
1381
1382static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1383{
1384 char sctl_path[MAXPATHLEN+1];
1385 int ret = -1;
1386 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001387 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001388
1389 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1390
1391 if (stat(sctl_path, &st))
1392 return 1;
1393
1394 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1395 goto out;
1396
1397 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1398 free(sctl);
1399 goto out;
1400 }
1401
1402 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1403
1404 ret = 0;
1405
1406out:
1407 return ret;
1408}
1409
1410#endif
1411
Emeric Brune1f38db2012-09-03 20:36:47 +02001412void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1413{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001414 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001415 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001416 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001417
1418 if (where & SSL_CB_HANDSHAKE_START) {
1419 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001420 if ((conn->flags & (CO_FL_CONNECTED | CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_CONNECTED) {
Emeric Brune1f38db2012-09-03 20:36:47 +02001421 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001422 conn->err_code = CO_ER_SSL_RENEG;
1423 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001424 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001425
1426 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1427 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1428 /* Long certificate chains optimz
1429 If write and read bios are differents, we
1430 consider that the buffering was activated,
1431 so we rise the output buffer size from 4k
1432 to 16k */
1433 write_bio = SSL_get_wbio(ssl);
1434 if (write_bio != SSL_get_rbio(ssl)) {
1435 BIO_set_write_buffer_size(write_bio, 16384);
1436 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1437 }
1438 }
1439 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001440}
1441
Emeric Brune64aef12012-09-21 13:15:06 +02001442/* Callback is called for each certificate of the chain during a verify
1443 ok is set to 1 if preverify detect no error on current certificate.
1444 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001445int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001446{
1447 SSL *ssl;
1448 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001449 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001450
1451 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001452 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001453
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001454 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001455
Emeric Brun81c00f02012-09-21 14:31:21 +02001456 if (ok) /* no errors */
1457 return ok;
1458
1459 depth = X509_STORE_CTX_get_error_depth(x_store);
1460 err = X509_STORE_CTX_get_error(x_store);
1461
1462 /* check if CA error needs to be ignored */
1463 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001464 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1465 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1466 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001467 }
1468
Willy Tarreau07d94e42018-09-20 10:57:52 +02001469 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001470 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001471 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001472 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001473 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001474
Willy Tarreau20879a02012-12-03 16:32:10 +01001475 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001476 return 0;
1477 }
1478
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001479 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1480 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001481
Emeric Brun81c00f02012-09-21 14:31:21 +02001482 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001483 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001484 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001485 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001486 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001487 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001488
Willy Tarreau20879a02012-12-03 16:32:10 +01001489 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001490 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001491}
1492
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001493static inline
1494void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001495 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001496{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001497 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001498 unsigned char *msg;
1499 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001500 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001501
1502 /* This function is called for "from client" and "to server"
1503 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001504 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001505 */
1506
1507 /* "write_p" is set to 0 is the bytes are received messages,
1508 * otherwise it is set to 1.
1509 */
1510 if (write_p != 0)
1511 return;
1512
1513 /* content_type contains the type of message received or sent
1514 * according with the SSL/TLS protocol spec. This message is
1515 * encoded with one byte. The value 256 (two bytes) is used
1516 * for designing the SSL/TLS record layer. According with the
1517 * rfc6101, the expected message (other than 256) are:
1518 * - change_cipher_spec(20)
1519 * - alert(21)
1520 * - handshake(22)
1521 * - application_data(23)
1522 * - (255)
1523 * We are interessed by the handshake and specially the client
1524 * hello.
1525 */
1526 if (content_type != 22)
1527 return;
1528
1529 /* The message length is at least 4 bytes, containing the
1530 * message type and the message length.
1531 */
1532 if (len < 4)
1533 return;
1534
1535 /* First byte of the handshake message id the type of
1536 * message. The konwn types are:
1537 * - hello_request(0)
1538 * - client_hello(1)
1539 * - server_hello(2)
1540 * - certificate(11)
1541 * - server_key_exchange (12)
1542 * - certificate_request(13)
1543 * - server_hello_done(14)
1544 * We are interested by the client hello.
1545 */
1546 msg = (unsigned char *)buf;
1547 if (msg[0] != 1)
1548 return;
1549
1550 /* Next three bytes are the length of the message. The total length
1551 * must be this decoded length + 4. If the length given as argument
1552 * is not the same, we abort the protocol dissector.
1553 */
1554 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1555 if (len < rec_len + 4)
1556 return;
1557 msg += 4;
1558 end = msg + rec_len;
1559 if (end < msg)
1560 return;
1561
1562 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1563 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001564 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1565 */
1566 msg += 1 + 1 + 4 + 28;
1567 if (msg > end)
1568 return;
1569
1570 /* Next, is session id:
1571 * if present, we have to jump by length + 1 for the size information
1572 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001573 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001574 if (msg[0] > 0)
1575 msg += msg[0];
1576 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001577 if (msg > end)
1578 return;
1579
1580 /* Next two bytes are the ciphersuite length. */
1581 if (msg + 2 > end)
1582 return;
1583 rec_len = (msg[0] << 8) + msg[1];
1584 msg += 2;
1585 if (msg + rec_len > end || msg + rec_len < msg)
1586 return;
1587
Willy Tarreaubafbe012017-11-24 17:34:44 +01001588 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001589 if (!capture)
1590 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001591 /* Compute the xxh64 of the ciphersuite. */
1592 capture->xxh64 = XXH64(msg, rec_len, 0);
1593
1594 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001595 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1596 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001597 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001598
1599 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001600}
1601
Emeric Brun29f037d2014-04-25 19:05:36 +02001602/* Callback is called for ssl protocol analyse */
1603void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1604{
Emeric Brun29f037d2014-04-25 19:05:36 +02001605#ifdef TLS1_RT_HEARTBEAT
1606 /* test heartbeat received (write_p is set to 0
1607 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001608 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001609 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001610 const unsigned char *p = buf;
1611 unsigned int payload;
1612
Emeric Brun29f037d2014-04-25 19:05:36 +02001613 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001614
1615 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1616 if (*p != TLS1_HB_REQUEST)
1617 return;
1618
Willy Tarreauaeed6722014-04-25 23:59:58 +02001619 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001620 goto kill_it;
1621
1622 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001623 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001624 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001625 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001626 /* We have a clear heartbleed attack (CVE-2014-0160), the
1627 * advertised payload is larger than the advertised packet
1628 * length, so we have garbage in the buffer between the
1629 * payload and the end of the buffer (p+len). We can't know
1630 * if the SSL stack is patched, and we don't know if we can
1631 * safely wipe out the area between p+3+len and payload.
1632 * So instead, we prevent the response from being sent by
1633 * setting the max_send_fragment to 0 and we report an SSL
1634 * error, which will kill this connection. It will be reported
1635 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001636 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1637 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001638 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001639 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1640 return;
1641 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001642#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001643 if (global_ssl.capture_cipherlist > 0)
1644 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001645}
1646
Bernard Spil13c53f82018-02-15 13:34:58 +01001647#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001648static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1649 const unsigned char *in, unsigned int inlen,
1650 void *arg)
1651{
1652 struct server *srv = arg;
1653
1654 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1655 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1656 return SSL_TLSEXT_ERR_OK;
1657 return SSL_TLSEXT_ERR_NOACK;
1658}
1659#endif
1660
1661#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001662/* This callback is used so that the server advertises the list of
1663 * negociable protocols for NPN.
1664 */
1665static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1666 unsigned int *len, void *arg)
1667{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001668 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001669
1670 *data = (const unsigned char *)conf->npn_str;
1671 *len = conf->npn_len;
1672 return SSL_TLSEXT_ERR_OK;
1673}
1674#endif
1675
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001676#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001677/* This callback is used so that the server advertises the list of
1678 * negociable protocols for ALPN.
1679 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001680static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1681 unsigned char *outlen,
1682 const unsigned char *server,
1683 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001684{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001685 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001686
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001687 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1688 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1689 return SSL_TLSEXT_ERR_NOACK;
1690 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001691 return SSL_TLSEXT_ERR_OK;
1692}
1693#endif
1694
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001695#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001696#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001697
Christopher Faulet30548802015-06-11 13:39:32 +02001698/* Create a X509 certificate with the specified servername and serial. This
1699 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001700static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001701ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001702{
Christopher Faulet7969a332015-10-09 11:15:03 +02001703 X509 *cacert = bind_conf->ca_sign_cert;
1704 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001705 SSL_CTX *ssl_ctx = NULL;
1706 X509 *newcrt = NULL;
1707 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001708 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001709 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001710 X509_NAME *name;
1711 const EVP_MD *digest;
1712 X509V3_CTX ctx;
1713 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001714 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001715
Christopher Faulet48a83322017-07-28 16:56:09 +02001716 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001717#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1718 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1719#else
1720 tmp_ssl = SSL_new(bind_conf->default_ctx);
1721 if (tmp_ssl)
1722 pkey = SSL_get_privatekey(tmp_ssl);
1723#endif
1724 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001725 goto mkcert_error;
1726
1727 /* Create the certificate */
1728 if (!(newcrt = X509_new()))
1729 goto mkcert_error;
1730
1731 /* Set version number for the certificate (X509v3) and the serial
1732 * number */
1733 if (X509_set_version(newcrt, 2L) != 1)
1734 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001735 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001736
1737 /* Set duration for the certificate */
1738 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1739 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1740 goto mkcert_error;
1741
1742 /* set public key in the certificate */
1743 if (X509_set_pubkey(newcrt, pkey) != 1)
1744 goto mkcert_error;
1745
1746 /* Set issuer name from the CA */
1747 if (!(name = X509_get_subject_name(cacert)))
1748 goto mkcert_error;
1749 if (X509_set_issuer_name(newcrt, name) != 1)
1750 goto mkcert_error;
1751
1752 /* Set the subject name using the same, but the CN */
1753 name = X509_NAME_dup(name);
1754 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1755 (const unsigned char *)servername,
1756 -1, -1, 0) != 1) {
1757 X509_NAME_free(name);
1758 goto mkcert_error;
1759 }
1760 if (X509_set_subject_name(newcrt, name) != 1) {
1761 X509_NAME_free(name);
1762 goto mkcert_error;
1763 }
1764 X509_NAME_free(name);
1765
1766 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001767 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001768 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1769 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1770 X509_EXTENSION *ext;
1771
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001772 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001773 goto mkcert_error;
1774 if (!X509_add_ext(newcrt, ext, -1)) {
1775 X509_EXTENSION_free(ext);
1776 goto mkcert_error;
1777 }
1778 X509_EXTENSION_free(ext);
1779 }
1780
1781 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001782
1783 key_type = EVP_PKEY_base_id(capkey);
1784
1785 if (key_type == EVP_PKEY_DSA)
1786 digest = EVP_sha1();
1787 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001788 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001789 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001790 digest = EVP_sha256();
1791 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001792#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001793 int nid;
1794
1795 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1796 goto mkcert_error;
1797 if (!(digest = EVP_get_digestbynid(nid)))
1798 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001799#else
1800 goto mkcert_error;
1801#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001802 }
1803
Christopher Faulet31af49d2015-06-09 17:29:50 +02001804 if (!(X509_sign(newcrt, capkey, digest)))
1805 goto mkcert_error;
1806
1807 /* Create and set the new SSL_CTX */
1808 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1809 goto mkcert_error;
1810 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1811 goto mkcert_error;
1812 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1813 goto mkcert_error;
1814 if (!SSL_CTX_check_private_key(ssl_ctx))
1815 goto mkcert_error;
1816
1817 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001818
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001819#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001820 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001821#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001822#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1823 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001824 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001825 EC_KEY *ecc;
1826 int nid;
1827
1828 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1829 goto end;
1830 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1831 goto end;
1832 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1833 EC_KEY_free(ecc);
1834 }
1835#endif
1836 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001837 return ssl_ctx;
1838
1839 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001840 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001841 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001842 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1843 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001844 return NULL;
1845}
1846
Christopher Faulet7969a332015-10-09 11:15:03 +02001847SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001848ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001849{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001850 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001851
1852 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001853}
1854
Christopher Faulet30548802015-06-11 13:39:32 +02001855/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001856 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001857SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001858ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001859{
1860 struct lru64 *lru = NULL;
1861
1862 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001863 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001864 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001865 if (lru && lru->domain) {
1866 if (ssl)
1867 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001868 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001869 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001870 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001871 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001872 }
1873 return NULL;
1874}
1875
Emeric Brun821bb9b2017-06-15 16:37:39 +02001876/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1877 * function is not thread-safe, it should only be used to check if a certificate
1878 * exists in the lru cache (with no warranty it will not be removed by another
1879 * thread). It is kept for backward compatibility. */
1880SSL_CTX *
1881ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1882{
1883 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1884}
1885
Christopher Fauletd2cab922015-07-28 16:03:47 +02001886/* Set a certificate int the LRU cache used to store generated
1887 * certificate. Return 0 on success, otherwise -1 */
1888int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001889ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001890{
1891 struct lru64 *lru = NULL;
1892
1893 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001894 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001895 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001896 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001897 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001898 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001899 }
Christopher Faulet30548802015-06-11 13:39:32 +02001900 if (lru->domain && lru->data)
1901 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001902 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001903 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001904 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001905 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001906 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001907}
1908
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001909/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001910unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001911ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001912{
1913 return XXH32(data, len, ssl_ctx_lru_seed);
1914}
1915
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001916/* Generate a cert and immediately assign it to the SSL session so that the cert's
1917 * refcount is maintained regardless of the cert's presence in the LRU cache.
1918 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001919static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001920ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001921{
1922 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001923 SSL_CTX *ssl_ctx = NULL;
1924 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001925 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001927 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001928 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001929 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001930 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001931 if (lru && lru->domain)
1932 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001933 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001934 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001935 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001936 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001937 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001938 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001939 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001940 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001941 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001942 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001943 SSL_set_SSL_CTX(ssl, ssl_ctx);
1944 /* No LRU cache, this CTX will be released as soon as the session dies */
1945 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001946 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001947 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001948 return 0;
1949}
1950static int
1951ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1952{
1953 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001954 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001955
1956 conn_get_to_addr(conn);
1957 if (conn->flags & CO_FL_ADDR_TO_SET) {
1958 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001959 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001960 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001961 }
1962 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001963}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001964#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001965
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001966
1967#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1968#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1969#endif
1970
1971#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1972#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1973#define SSL_renegotiate_pending(arg) 0
1974#endif
1975#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1976#define SSL_OP_SINGLE_ECDH_USE 0
1977#endif
1978#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1979#define SSL_OP_NO_TICKET 0
1980#endif
1981#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1982#define SSL_OP_NO_COMPRESSION 0
1983#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001984#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1985#undef SSL_OP_NO_SSLv3
1986#define SSL_OP_NO_SSLv3 0
1987#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001988#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1989#define SSL_OP_NO_TLSv1_1 0
1990#endif
1991#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1992#define SSL_OP_NO_TLSv1_2 0
1993#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001994#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001995#define SSL_OP_NO_TLSv1_3 0
1996#endif
1997#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1998#define SSL_OP_SINGLE_DH_USE 0
1999#endif
2000#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
2001#define SSL_OP_SINGLE_ECDH_USE 0
2002#endif
2003#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
2004#define SSL_MODE_RELEASE_BUFFERS 0
2005#endif
2006#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
2007#define SSL_MODE_SMALL_BUFFERS 0
2008#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02002009#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2010#define SSL_OP_PRIORITIZE_CHACHA 0
2011#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002013#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2015
2016static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002017{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002018#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002019 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2021#endif
2022}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002023static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2024 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2026}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002027static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002029 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002030 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2031#endif
2032}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002033static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002034#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002036 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2037#endif
2038}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002039/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002040static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2041/* Unusable in this context. */
2042static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2043static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2044static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2045static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2046static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002047#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002048typedef enum { SET_MIN, SET_MAX } set_context_func;
2049
2050static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2051 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002052 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2053}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2055 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2056 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2057}
2058static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2059 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002060 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2061}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002062static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2063 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2064 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2065}
2066static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2067 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002068 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2069}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002070static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2071 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2072 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2073}
2074static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2075 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002076 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2077}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002078static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2079 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2080 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2081}
2082static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002084 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002085 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2086#endif
2087}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002088static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2089#if SSL_OP_NO_TLSv1_3
2090 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2091 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002092#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002093}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002094#endif
2095static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2096static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002097
2098static struct {
2099 int option;
2100 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002101 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2102 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002103 const char *name;
2104} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002105 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2106 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2107 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2108 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2109 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2110 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002111};
2112
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002113static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2114{
2115 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2116 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2117 SSL_set_SSL_CTX(ssl, ctx);
2118}
2119
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002120#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121
2122static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2123{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002124 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002126
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002127 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2128 return SSL_TLSEXT_ERR_OK;
2129 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002130}
2131
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002132#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002133static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2134{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002135 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002136#else
2137static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2138{
2139#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 struct connection *conn;
2141 struct bind_conf *s;
2142 const uint8_t *extension_data;
2143 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002144 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002145
2146 char *wildp = NULL;
2147 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002148 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002149 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002150 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002151 int i;
2152
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002153 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002154 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002155
Olivier Houchard9679ac92017-10-27 14:58:08 +02002156 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002157 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002158#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002159 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2160 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002161#else
2162 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2163#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002164 /*
2165 * The server_name extension was given too much extensibility when it
2166 * was written, so parsing the normal case is a bit complex.
2167 */
2168 size_t len;
2169 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002170 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002171 /* Extract the length of the supplied list of names. */
2172 len = (*extension_data++) << 8;
2173 len |= *extension_data++;
2174 if (len + 2 != extension_len)
2175 goto abort;
2176 /*
2177 * The list in practice only has a single element, so we only consider
2178 * the first one.
2179 */
2180 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2181 goto abort;
2182 extension_len = len - 1;
2183 /* Now we can finally pull out the byte array with the actual hostname. */
2184 if (extension_len <= 2)
2185 goto abort;
2186 len = (*extension_data++) << 8;
2187 len |= *extension_data++;
2188 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2189 || memchr(extension_data, 0, len) != NULL)
2190 goto abort;
2191 servername = extension_data;
2192 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002193 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002194#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2195 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002196 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002197 }
2198#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002200 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002201 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002202 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002203 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002204 goto abort;
2205 }
2206
2207 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002208#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002209 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002210#else
2211 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2212#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002213 uint8_t sign;
2214 size_t len;
2215 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002216 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002217 len = (*extension_data++) << 8;
2218 len |= *extension_data++;
2219 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002221 if (len % 2 != 0)
2222 goto abort;
2223 for (; len > 0; len -= 2) {
2224 extension_data++; /* hash */
2225 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002226 switch (sign) {
2227 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002228 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002229 break;
2230 case TLSEXT_signature_ecdsa:
2231 has_ecdsa_sig = 1;
2232 break;
2233 default:
2234 continue;
2235 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002236 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 break;
2238 }
2239 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002240 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002241 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002242 }
2243 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 const SSL_CIPHER *cipher;
2245 size_t len;
2246 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002247 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002248#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 len = ctx->cipher_suites_len;
2250 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002251#else
2252 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2253#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002254 if (len % 2 != 0)
2255 goto abort;
2256 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002257#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002258 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002259 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002260#else
2261 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2262#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002263 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002264 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 break;
2266 }
2267 }
2268 }
2269
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002270 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002271 trash.area[i] = tolower(servername[i]);
2272 if (!wildp && (trash.area[i] == '.'))
2273 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002274 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002275 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002276
2277 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002278 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002279
2280 /* lookup a not neg filter */
2281 for (n = node; n; n = ebmb_next_dup(n)) {
2282 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002283 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002285 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002286 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 break;
2288 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002289 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002290 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002291 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002292 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002293 if (!node_anonymous)
2294 node_anonymous = n;
2295 break;
2296 }
2297 }
2298 }
2299 if (wildp) {
2300 /* lookup in wildcards names */
2301 node = ebst_lookup(&s->sni_w_ctx, wildp);
2302 for (n = node; n; n = ebmb_next_dup(n)) {
2303 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002304 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002306 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002308 break;
2309 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002310 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002311 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002312 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002313 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002314 if (!node_anonymous)
2315 node_anonymous = n;
2316 break;
2317 }
2318 }
2319 }
2320 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002321 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002322 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2323 : ((has_rsa_sig && node_rsa) ? node_rsa
2324 : (node_anonymous ? node_anonymous
2325 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2326 : node_rsa /* no rsa signature case (far far away) */
2327 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002328 if (node) {
2329 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002330 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002331 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002332 if (conf) {
2333 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2334 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2335 if (conf->early_data)
2336 allow_early = 1;
2337 }
2338 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002339 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002340#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002341 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002342 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002343 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002344 }
2345#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002346 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002347 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002348 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002349 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002350allow_early:
2351#ifdef OPENSSL_IS_BORINGSSL
2352 if (allow_early)
2353 SSL_set_early_data_enabled(ssl, 1);
2354#else
2355 if (!allow_early)
2356 SSL_set_max_early_data(ssl, 0);
2357#endif
2358 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 abort:
2360 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2361 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002362#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002363 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002364#else
2365 *al = SSL_AD_UNRECOGNIZED_NAME;
2366 return 0;
2367#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002368}
2369
2370#else /* OPENSSL_IS_BORINGSSL */
2371
Emeric Brunfc0421f2012-09-07 17:30:07 +02002372/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2373 * warning when no match is found, which implies the default (first) cert
2374 * will keep being used.
2375 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002376static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002377{
2378 const char *servername;
2379 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002380 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002381 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002382 int i;
2383 (void)al; /* shut gcc stupid warning */
2384
2385 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002386 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002387#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002388 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2389 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002390#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002391 if (s->strict_sni)
2392 return SSL_TLSEXT_ERR_ALERT_FATAL;
2393 ssl_sock_switchctx_set(ssl, s->default_ctx);
2394 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002395 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002396
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002397 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002398 if (!servername[i])
2399 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002400 trash.area[i] = tolower(servername[i]);
2401 if (!wildp && (trash.area[i] == '.'))
2402 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002403 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002404 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002405
2406 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002407 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002408
2409 /* lookup a not neg filter */
2410 for (n = node; n; n = ebmb_next_dup(n)) {
2411 if (!container_of(n, struct sni_ctx, name)->neg) {
2412 node = n;
2413 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002414 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002415 }
2416 if (!node && wildp) {
2417 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002418 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002419 }
2420 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002422 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2423 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002424 return SSL_TLSEXT_ERR_OK;
2425 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002426#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002427 if (s->strict_sni)
2428 return SSL_TLSEXT_ERR_ALERT_FATAL;
2429 ssl_sock_switchctx_set(ssl, s->default_ctx);
2430 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002431 }
2432
2433 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002434 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002435 return SSL_TLSEXT_ERR_OK;
2436}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002437#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002438#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2439
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002440#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002441
2442static DH * ssl_get_dh_1024(void)
2443{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002444 static unsigned char dh1024_p[]={
2445 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2446 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2447 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2448 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2449 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2450 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2451 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2452 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2453 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2454 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2455 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2456 };
2457 static unsigned char dh1024_g[]={
2458 0x02,
2459 };
2460
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002461 BIGNUM *p;
2462 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002463 DH *dh = DH_new();
2464 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002465 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2466 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002467
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002469 DH_free(dh);
2470 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002471 } else {
2472 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002473 }
2474 }
2475 return dh;
2476}
2477
2478static DH *ssl_get_dh_2048(void)
2479{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002480 static unsigned char dh2048_p[]={
2481 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2482 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2483 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2484 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2485 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2486 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2487 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2488 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2489 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2490 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2491 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2492 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2493 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2494 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2495 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2496 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2497 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2498 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2499 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2500 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2501 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2502 0xB7,0x1F,0x77,0xF3,
2503 };
2504 static unsigned char dh2048_g[]={
2505 0x02,
2506 };
2507
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002508 BIGNUM *p;
2509 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002510 DH *dh = DH_new();
2511 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002512 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2513 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002514
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002515 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002516 DH_free(dh);
2517 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 } else {
2519 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002520 }
2521 }
2522 return dh;
2523}
2524
2525static DH *ssl_get_dh_4096(void)
2526{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002527 static unsigned char dh4096_p[]={
2528 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2529 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2530 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2531 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2532 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2533 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2534 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2535 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2536 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2537 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2538 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2539 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2540 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2541 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2542 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2543 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2544 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2545 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2546 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2547 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2548 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2549 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2550 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2551 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2552 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2553 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2554 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2555 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2556 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2557 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2558 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2559 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2560 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2561 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2562 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2563 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2564 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2565 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2566 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2567 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2568 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2569 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2570 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002571 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002572 static unsigned char dh4096_g[]={
2573 0x02,
2574 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002575
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002576 BIGNUM *p;
2577 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 DH *dh = DH_new();
2579 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002580 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2581 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002582
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002583 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002584 DH_free(dh);
2585 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002586 } else {
2587 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002588 }
2589 }
2590 return dh;
2591}
2592
2593/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002594 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002595static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2596{
2597 DH *dh = NULL;
2598 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002599 int type;
2600
2601 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002602
2603 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2604 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2605 */
2606 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2607 keylen = EVP_PKEY_bits(pkey);
2608 }
2609
Willy Tarreauef934602016-12-22 23:12:01 +01002610 if (keylen > global_ssl.default_dh_param) {
2611 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002612 }
2613
Remi Gacogned3a341a2015-05-29 16:26:17 +02002614 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002615 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002616 }
2617 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002618 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002619 }
2620 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002621 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 }
2623
2624 return dh;
2625}
2626
Remi Gacogne47783ef2015-05-29 15:53:22 +02002627static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002628{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002629 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002630 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002631
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002632 if (in == NULL)
2633 goto end;
2634
Remi Gacogne47783ef2015-05-29 15:53:22 +02002635 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002636 goto end;
2637
Remi Gacogne47783ef2015-05-29 15:53:22 +02002638 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2639
2640end:
2641 if (in)
2642 BIO_free(in);
2643
Emeric Brune1b4ed42018-08-16 15:14:12 +02002644 ERR_clear_error();
2645
Remi Gacogne47783ef2015-05-29 15:53:22 +02002646 return dh;
2647}
2648
2649int ssl_sock_load_global_dh_param_from_file(const char *filename)
2650{
2651 global_dh = ssl_sock_get_dh_from_file(filename);
2652
2653 if (global_dh) {
2654 return 0;
2655 }
2656
2657 return -1;
2658}
2659
2660/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002661 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002662int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2663{
2664 int ret = -1;
2665 DH *dh = ssl_sock_get_dh_from_file(file);
2666
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002667 if (dh) {
2668 ret = 1;
2669 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002670
2671 if (ssl_dh_ptr_index >= 0) {
2672 /* store a pointer to the DH params to avoid complaining about
2673 ssl-default-dh-param not being set for this SSL_CTX */
2674 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2675 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002676 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002677 else if (global_dh) {
2678 SSL_CTX_set_tmp_dh(ctx, global_dh);
2679 ret = 0; /* DH params not found */
2680 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002681 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002682 /* Clear openssl global errors stack */
2683 ERR_clear_error();
2684
Willy Tarreauef934602016-12-22 23:12:01 +01002685 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002686 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002687 if (local_dh_1024 == NULL)
2688 local_dh_1024 = ssl_get_dh_1024();
2689
Remi Gacogne8de54152014-07-15 11:36:40 +02002690 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002691 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002692
Remi Gacogne8de54152014-07-15 11:36:40 +02002693 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002694 }
2695 else {
2696 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2697 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002698
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002699 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002700 }
Emeric Brun644cde02012-12-14 11:21:13 +01002701
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002702end:
2703 if (dh)
2704 DH_free(dh);
2705
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002706 return ret;
2707}
2708#endif
2709
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002710static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002711 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002712{
2713 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002714 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002715 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002716
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002717 if (*name == '!') {
2718 neg = 1;
2719 name++;
2720 }
2721 if (*name == '*') {
2722 wild = 1;
2723 name++;
2724 }
2725 /* !* filter is a nop */
2726 if (neg && wild)
2727 return order;
2728 if (*name) {
2729 int j, len;
2730 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002731 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002732 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002733 if (j >= trash.size)
2734 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002735 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002736
2737 /* Check for duplicates. */
2738 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002739 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002740 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002741 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002742 for (; node; node = ebmb_next_dup(node)) {
2743 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002744 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002745 return order;
2746 }
2747
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002748 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002749 if (!sc)
2750 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002751 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002752 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002753 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002754 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002755 sc->order = order++;
2756 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002757 if (kinfo.sig != TLSEXT_signature_anonymous)
2758 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002759 if (wild)
2760 ebst_insert(&s->sni_w_ctx, &sc->name);
2761 else
2762 ebst_insert(&s->sni_ctx, &sc->name);
2763 }
2764 return order;
2765}
2766
yanbzhu488a4d22015-12-01 15:16:07 -05002767
2768/* The following code is used for loading multiple crt files into
2769 * SSL_CTX's based on CN/SAN
2770 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002771#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002772/* This is used to preload the certifcate, private key
2773 * and Cert Chain of a file passed in via the crt
2774 * argument
2775 *
2776 * This way, we do not have to read the file multiple times
2777 */
2778struct cert_key_and_chain {
2779 X509 *cert;
2780 EVP_PKEY *key;
2781 unsigned int num_chain_certs;
2782 /* This is an array of X509 pointers */
2783 X509 **chain_certs;
2784};
2785
yanbzhu08ce6ab2015-12-02 13:01:29 -05002786#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2787
2788struct key_combo_ctx {
2789 SSL_CTX *ctx;
2790 int order;
2791};
2792
2793/* Map used for processing multiple keypairs for a single purpose
2794 *
2795 * This maps CN/SNI name to certificate type
2796 */
2797struct sni_keytype {
2798 int keytypes; /* BITMASK for keytypes */
2799 struct ebmb_node name; /* node holding the servername value */
2800};
2801
2802
yanbzhu488a4d22015-12-01 15:16:07 -05002803/* Frees the contents of a cert_key_and_chain
2804 */
2805static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2806{
2807 int i;
2808
2809 if (!ckch)
2810 return;
2811
2812 /* Free the certificate and set pointer to NULL */
2813 if (ckch->cert)
2814 X509_free(ckch->cert);
2815 ckch->cert = NULL;
2816
2817 /* Free the key and set pointer to NULL */
2818 if (ckch->key)
2819 EVP_PKEY_free(ckch->key);
2820 ckch->key = NULL;
2821
2822 /* Free each certificate in the chain */
2823 for (i = 0; i < ckch->num_chain_certs; i++) {
2824 if (ckch->chain_certs[i])
2825 X509_free(ckch->chain_certs[i]);
2826 }
2827
2828 /* Free the chain obj itself and set to NULL */
2829 if (ckch->num_chain_certs > 0) {
2830 free(ckch->chain_certs);
2831 ckch->num_chain_certs = 0;
2832 ckch->chain_certs = NULL;
2833 }
2834
2835}
2836
2837/* checks if a key and cert exists in the ckch
2838 */
2839static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2840{
2841 return (ckch->cert != NULL && ckch->key != NULL);
2842}
2843
2844
2845/* Loads the contents of a crt file (path) into a cert_key_and_chain
2846 * This allows us to carry the contents of the file without having to
2847 * read the file multiple times.
2848 *
2849 * returns:
2850 * 0 on Success
2851 * 1 on SSL Failure
2852 * 2 on file not found
2853 */
2854static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2855{
2856
2857 BIO *in;
2858 X509 *ca = NULL;
2859 int ret = 1;
2860
2861 ssl_sock_free_cert_key_and_chain_contents(ckch);
2862
2863 in = BIO_new(BIO_s_file());
2864 if (in == NULL)
2865 goto end;
2866
2867 if (BIO_read_filename(in, path) <= 0)
2868 goto end;
2869
yanbzhu488a4d22015-12-01 15:16:07 -05002870 /* Read Private Key */
2871 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2872 if (ckch->key == NULL) {
2873 memprintf(err, "%sunable to load private key from file '%s'.\n",
2874 err && *err ? *err : "", path);
2875 goto end;
2876 }
2877
Willy Tarreaubb137a82016-04-06 19:02:38 +02002878 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002879 if (BIO_reset(in) == -1) {
2880 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2881 err && *err ? *err : "", path);
2882 goto end;
2883 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002884
2885 /* Read Certificate */
2886 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2887 if (ckch->cert == NULL) {
2888 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2889 err && *err ? *err : "", path);
2890 goto end;
2891 }
2892
yanbzhu488a4d22015-12-01 15:16:07 -05002893 /* Read Certificate Chain */
2894 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2895 /* Grow the chain certs */
2896 ckch->num_chain_certs++;
2897 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2898
2899 /* use - 1 here since we just incremented it above */
2900 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2901 }
2902 ret = ERR_get_error();
2903 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2904 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2905 err && *err ? *err : "", path);
2906 ret = 1;
2907 goto end;
2908 }
2909
2910 ret = 0;
2911
2912end:
2913
2914 ERR_clear_error();
2915 if (in)
2916 BIO_free(in);
2917
2918 /* Something went wrong in one of the reads */
2919 if (ret != 0)
2920 ssl_sock_free_cert_key_and_chain_contents(ckch);
2921
2922 return ret;
2923}
2924
2925/* Loads the info in ckch into ctx
2926 * Currently, this does not process any information about ocsp, dhparams or
2927 * sctl
2928 * Returns
2929 * 0 on success
2930 * 1 on failure
2931 */
2932static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2933{
2934 int i = 0;
2935
2936 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2937 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2938 err && *err ? *err : "", path);
2939 return 1;
2940 }
2941
2942 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2943 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2944 err && *err ? *err : "", path);
2945 return 1;
2946 }
2947
yanbzhu488a4d22015-12-01 15:16:07 -05002948 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2949 for (i = 0; i < ckch->num_chain_certs; i++) {
2950 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002951 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2952 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002953 return 1;
2954 }
2955 }
2956
2957 if (SSL_CTX_check_private_key(ctx) <= 0) {
2958 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2959 err && *err ? *err : "", path);
2960 return 1;
2961 }
2962
2963 return 0;
2964}
2965
yanbzhu08ce6ab2015-12-02 13:01:29 -05002966
2967static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2968{
2969 struct sni_keytype *s_kt = NULL;
2970 struct ebmb_node *node;
2971 int i;
2972
2973 for (i = 0; i < trash.size; i++) {
2974 if (!str[i])
2975 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002976 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002977 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002978 trash.area[i] = 0;
2979 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002980 if (!node) {
2981 /* CN not found in tree */
2982 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2983 /* Using memcpy here instead of strncpy.
2984 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2985 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2986 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002987 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002988 s_kt->keytypes = 0;
2989 ebst_insert(sni_keytypes, &s_kt->name);
2990 } else {
2991 /* CN found in tree */
2992 s_kt = container_of(node, struct sni_keytype, name);
2993 }
2994
2995 /* Mark that this CN has the keytype of key_index via keytypes mask */
2996 s_kt->keytypes |= 1<<key_index;
2997
2998}
2999
3000
3001/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3002 * If any are found, group these files into a set of SSL_CTX*
3003 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3004 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003005 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003006 *
3007 * Returns
3008 * 0 on success
3009 * 1 on failure
3010 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003011static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3012 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003013{
3014 char fp[MAXPATHLEN+1] = {0};
3015 int n = 0;
3016 int i = 0;
3017 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3018 struct eb_root sni_keytypes_map = { {0} };
3019 struct ebmb_node *node;
3020 struct ebmb_node *next;
3021 /* Array of SSL_CTX pointers corresponding to each possible combo
3022 * of keytypes
3023 */
3024 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3025 int rv = 0;
3026 X509_NAME *xname = NULL;
3027 char *str = NULL;
3028#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3029 STACK_OF(GENERAL_NAME) *names = NULL;
3030#endif
3031
3032 /* Load all possible certs and keys */
3033 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3034 struct stat buf;
3035
3036 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3037 if (stat(fp, &buf) == 0) {
3038 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3039 rv = 1;
3040 goto end;
3041 }
3042 }
3043 }
3044
3045 /* Process each ckch and update keytypes for each CN/SAN
3046 * for example, if CN/SAN www.a.com is associated with
3047 * certs with keytype 0 and 2, then at the end of the loop,
3048 * www.a.com will have:
3049 * keyindex = 0 | 1 | 4 = 5
3050 */
3051 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3052
3053 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3054 continue;
3055
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003056 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003057 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003058 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3059 } else {
3060 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3061 * so the line that contains logic is marked via comments
3062 */
3063 xname = X509_get_subject_name(certs_and_keys[n].cert);
3064 i = -1;
3065 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3066 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003067 ASN1_STRING *value;
3068 value = X509_NAME_ENTRY_get_data(entry);
3069 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003070 /* Important line is here */
3071 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003072
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003073 OPENSSL_free(str);
3074 str = NULL;
3075 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003076 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003078 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003079#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003080 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3081 if (names) {
3082 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3083 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003085 if (name->type == GEN_DNS) {
3086 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3087 /* Important line is here */
3088 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003089
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003090 OPENSSL_free(str);
3091 str = NULL;
3092 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003093 }
3094 }
3095 }
3096 }
3097#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3098 }
3099
3100 /* If no files found, return error */
3101 if (eb_is_empty(&sni_keytypes_map)) {
3102 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3103 err && *err ? *err : "", path);
3104 rv = 1;
3105 goto end;
3106 }
3107
3108 /* We now have a map of CN/SAN to keytypes that are loaded in
3109 * Iterate through the map to create the SSL_CTX's (if needed)
3110 * and add each CTX to the SNI tree
3111 *
3112 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003113 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003114 * combination is denoted by the key in the map. Each key
3115 * has a value between 1 and 2^n - 1. Conveniently, the array
3116 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3117 * entry in the array to correspond to the unique combo (key)
3118 * associated with i. This unique key combo (i) will be associated
3119 * with combos[i-1]
3120 */
3121
3122 node = ebmb_first(&sni_keytypes_map);
3123 while (node) {
3124 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003125 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003126 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003127
3128 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3129 i = container_of(node, struct sni_keytype, name)->keytypes;
3130 cur_ctx = key_combos[i-1].ctx;
3131
3132 if (cur_ctx == NULL) {
3133 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003134 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003135 if (cur_ctx == NULL) {
3136 memprintf(err, "%sunable to allocate SSL context.\n",
3137 err && *err ? *err : "");
3138 rv = 1;
3139 goto end;
3140 }
3141
yanbzhube2774d2015-12-10 15:07:30 -05003142 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003143 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3144 if (i & (1<<n)) {
3145 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003146 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3147 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003148 SSL_CTX_free(cur_ctx);
3149 rv = 1;
3150 goto end;
3151 }
yanbzhube2774d2015-12-10 15:07:30 -05003152
3153#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3154 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003155 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003156 if (err)
3157 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003158 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003159 SSL_CTX_free(cur_ctx);
3160 rv = 1;
3161 goto end;
3162 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003163#elif (defined OPENSSL_IS_BORINGSSL)
3164 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003165#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003166 }
3167 }
3168
3169 /* Load DH params into the ctx to support DHE keys */
3170#ifndef OPENSSL_NO_DH
3171 if (ssl_dh_ptr_index >= 0)
3172 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3173
3174 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3175 if (rv < 0) {
3176 if (err)
3177 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3178 *err ? *err : "", path);
3179 rv = 1;
3180 goto end;
3181 }
3182#endif
3183
3184 /* Update key_combos */
3185 key_combos[i-1].ctx = cur_ctx;
3186 }
3187
3188 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003189 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003190 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003191 node = ebmb_next(node);
3192 }
3193
3194
3195 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3196 if (!bind_conf->default_ctx) {
3197 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3198 if (key_combos[i].ctx) {
3199 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003200 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003201 break;
3202 }
3203 }
3204 }
3205
3206end:
3207
3208 if (names)
3209 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3210
3211 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3212 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3213
3214 node = ebmb_first(&sni_keytypes_map);
3215 while (node) {
3216 next = ebmb_next(node);
3217 ebmb_delete(node);
3218 node = next;
3219 }
3220
3221 return rv;
3222}
3223#else
3224/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003225static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3226 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003227{
3228 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3229 err && *err ? *err : "", path, strerror(errno));
3230 return 1;
3231}
3232
yanbzhu488a4d22015-12-01 15:16:07 -05003233#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3234
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3236 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3237 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003238static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3239 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003240{
3241 BIO *in;
3242 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003243 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003244 int ret = -1;
3245 int order = 0;
3246 X509_NAME *xname;
3247 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003248 pem_password_cb *passwd_cb;
3249 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003250 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003251 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003252
Emeric Brunfc0421f2012-09-07 17:30:07 +02003253#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3254 STACK_OF(GENERAL_NAME) *names;
3255#endif
3256
3257 in = BIO_new(BIO_s_file());
3258 if (in == NULL)
3259 goto end;
3260
3261 if (BIO_read_filename(in, file) <= 0)
3262 goto end;
3263
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003264
3265 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3266 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3267
3268 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003269 if (x == NULL)
3270 goto end;
3271
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003272 pkey = X509_get_pubkey(x);
3273 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003274 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003275 switch(EVP_PKEY_base_id(pkey)) {
3276 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003277 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003278 break;
3279 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003280 kinfo.sig = TLSEXT_signature_ecdsa;
3281 break;
3282 case EVP_PKEY_DSA:
3283 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003284 break;
3285 }
3286 EVP_PKEY_free(pkey);
3287 }
3288
Emeric Brun50bcecc2013-04-22 13:05:23 +02003289 if (fcount) {
3290 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003291 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003292 }
3293 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003295 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3296 if (names) {
3297 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3298 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3299 if (name->type == GEN_DNS) {
3300 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003301 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003302 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003303 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003304 }
3305 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003306 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003307 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003308#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003309 xname = X509_get_subject_name(x);
3310 i = -1;
3311 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3312 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003313 ASN1_STRING *value;
3314
3315 value = X509_NAME_ENTRY_get_data(entry);
3316 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003317 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003318 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003319 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003320 }
3321 }
3322
3323 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3324 if (!SSL_CTX_use_certificate(ctx, x))
3325 goto end;
3326
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003327#ifdef SSL_CTX_clear_extra_chain_certs
3328 SSL_CTX_clear_extra_chain_certs(ctx);
3329#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003330 if (ctx->extra_certs != NULL) {
3331 sk_X509_pop_free(ctx->extra_certs, X509_free);
3332 ctx->extra_certs = NULL;
3333 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003334#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003335
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003336 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003337 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3338 X509_free(ca);
3339 goto end;
3340 }
3341 }
3342
3343 err = ERR_get_error();
3344 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3345 /* we successfully reached the last cert in the file */
3346 ret = 1;
3347 }
3348 ERR_clear_error();
3349
3350end:
3351 if (x)
3352 X509_free(x);
3353
3354 if (in)
3355 BIO_free(in);
3356
3357 return ret;
3358}
3359
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003360static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3361 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003362{
3363 int ret;
3364 SSL_CTX *ctx;
3365
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003366 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003368 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3369 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003370 return 1;
3371 }
3372
3373 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003374 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3375 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003376 SSL_CTX_free(ctx);
3377 return 1;
3378 }
3379
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003380 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003381 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003382 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3383 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003384 if (ret < 0) /* serious error, must do that ourselves */
3385 SSL_CTX_free(ctx);
3386 return 1;
3387 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003388
3389 if (SSL_CTX_check_private_key(ctx) <= 0) {
3390 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3391 err && *err ? *err : "", path);
3392 return 1;
3393 }
3394
Emeric Brunfc0421f2012-09-07 17:30:07 +02003395 /* we must not free the SSL_CTX anymore below, since it's already in
3396 * the tree, so it will be discovered and cleaned in time.
3397 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003398#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003399 /* store a NULL pointer to indicate we have not yet loaded
3400 a custom DH param file */
3401 if (ssl_dh_ptr_index >= 0) {
3402 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3403 }
3404
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003405 ret = ssl_sock_load_dh_params(ctx, path);
3406 if (ret < 0) {
3407 if (err)
3408 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3409 *err ? *err : "", path);
3410 return 1;
3411 }
3412#endif
3413
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003414#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003415 ret = ssl_sock_load_ocsp(ctx, path);
3416 if (ret < 0) {
3417 if (err)
3418 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3419 *err ? *err : "", path);
3420 return 1;
3421 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003422#elif (defined OPENSSL_IS_BORINGSSL)
3423 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003424#endif
3425
Daniel Jakots54ffb912015-11-06 20:02:41 +01003426#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003427 if (sctl_ex_index >= 0) {
3428 ret = ssl_sock_load_sctl(ctx, path);
3429 if (ret < 0) {
3430 if (err)
3431 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3432 *err ? *err : "", path);
3433 return 1;
3434 }
3435 }
3436#endif
3437
Emeric Brunfc0421f2012-09-07 17:30:07 +02003438#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003439 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003440 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3441 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003442 return 1;
3443 }
3444#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003445 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003446 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003447 bind_conf->default_ssl_conf = ssl_conf;
3448 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003449
3450 return 0;
3451}
3452
Willy Tarreau03209342016-12-22 17:08:28 +01003453int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003454{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003455 struct dirent **de_list;
3456 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003457 DIR *dir;
3458 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003459 char *end;
3460 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003461 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003462#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3463 int is_bundle;
3464 int j;
3465#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467 if (stat(path, &buf) == 0) {
3468 dir = opendir(path);
3469 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003470 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003471
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 /* strip trailing slashes, including first one */
3473 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3474 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003475
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476 n = scandir(path, &de_list, 0, alphasort);
3477 if (n < 0) {
3478 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3479 err && *err ? *err : "", path, strerror(errno));
3480 cfgerr++;
3481 }
3482 else {
3483 for (i = 0; i < n; i++) {
3484 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003485
yanbzhu08ce6ab2015-12-02 13:01:29 -05003486 end = strrchr(de->d_name, '.');
3487 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3488 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003489
yanbzhu08ce6ab2015-12-02 13:01:29 -05003490 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3491 if (stat(fp, &buf) != 0) {
3492 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3493 err && *err ? *err : "", fp, strerror(errno));
3494 cfgerr++;
3495 goto ignore_entry;
3496 }
3497 if (!S_ISREG(buf.st_mode))
3498 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003499
3500#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3501 is_bundle = 0;
3502 /* Check if current entry in directory is part of a multi-cert bundle */
3503
3504 if (end) {
3505 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3506 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3507 is_bundle = 1;
3508 break;
3509 }
3510 }
3511
3512 if (is_bundle) {
3513 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3514 int dp_len;
3515
3516 dp_len = end - de->d_name;
3517 snprintf(dp, dp_len + 1, "%s", de->d_name);
3518
3519 /* increment i and free de until we get to a non-bundle cert
3520 * Note here that we look at de_list[i + 1] before freeing de
3521 * this is important since ignore_entry will free de
3522 */
3523 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3524 free(de);
3525 i++;
3526 de = de_list[i];
3527 }
3528
3529 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003530 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003531
3532 /* Successfully processed the bundle */
3533 goto ignore_entry;
3534 }
3535 }
3536
3537#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003539ignore_entry:
3540 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003541 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003542 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003543 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003544 closedir(dir);
3545 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003546 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003547
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003548 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003549
Emeric Brunfc0421f2012-09-07 17:30:07 +02003550 return cfgerr;
3551}
3552
Thierry Fournier383085f2013-01-24 14:15:43 +01003553/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3554 * done once. Zero is returned if the operation fails. No error is returned
3555 * if the random is said as not implemented, because we expect that openssl
3556 * will use another method once needed.
3557 */
3558static int ssl_initialize_random()
3559{
3560 unsigned char random;
3561 static int random_initialized = 0;
3562
3563 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3564 random_initialized = 1;
3565
3566 return random_initialized;
3567}
3568
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003569/* release ssl bind conf */
3570void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003571{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003572 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003573#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003574 free(conf->npn_str);
3575 conf->npn_str = NULL;
3576#endif
3577#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3578 free(conf->alpn_str);
3579 conf->alpn_str = NULL;
3580#endif
3581 free(conf->ca_file);
3582 conf->ca_file = NULL;
3583 free(conf->crl_file);
3584 conf->crl_file = NULL;
3585 free(conf->ciphers);
3586 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003587#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3588 free(conf->ciphersuites);
3589 conf->ciphersuites = NULL;
3590#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003591 free(conf->curves);
3592 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003593 free(conf->ecdhe);
3594 conf->ecdhe = NULL;
3595 }
3596}
3597
3598int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3599{
3600 char thisline[CRT_LINESIZE];
3601 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003602 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003603 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003604 int linenum = 0;
3605 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003606
Willy Tarreauad1731d2013-04-02 17:35:58 +02003607 if ((f = fopen(file, "r")) == NULL) {
3608 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003609 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003610 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003611
3612 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003613 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003614 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003615 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003616 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003617 char *crt_path;
3618 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003619
3620 linenum++;
3621 end = line + strlen(line);
3622 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3623 /* Check if we reached the limit and the last char is not \n.
3624 * Watch out for the last line without the terminating '\n'!
3625 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003626 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3627 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003628 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003629 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003630 }
3631
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003632 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003633 newarg = 1;
3634 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003635 if (*line == '#' || *line == '\n' || *line == '\r') {
3636 /* end of string, end of loop */
3637 *line = 0;
3638 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003639 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003640 newarg = 1;
3641 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003642 } else if (*line == '[') {
3643 if (ssl_b) {
3644 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3645 cfgerr = 1;
3646 break;
3647 }
3648 if (!arg) {
3649 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3650 cfgerr = 1;
3651 break;
3652 }
3653 ssl_b = arg;
3654 newarg = 1;
3655 *line = 0;
3656 } else if (*line == ']') {
3657 if (ssl_e) {
3658 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003659 cfgerr = 1;
3660 break;
3661 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003662 if (!ssl_b) {
3663 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3664 cfgerr = 1;
3665 break;
3666 }
3667 ssl_e = arg;
3668 newarg = 1;
3669 *line = 0;
3670 } else if (newarg) {
3671 if (arg == MAX_CRT_ARGS) {
3672 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3673 cfgerr = 1;
3674 break;
3675 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003676 newarg = 0;
3677 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003678 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003679 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003680 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003681 if (cfgerr)
3682 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003683 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003684
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003685 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003686 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003687 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003688
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003689 crt_path = args[0];
3690 if (*crt_path != '/' && global_ssl.crt_base) {
3691 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3692 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3693 crt_path, linenum, file);
3694 cfgerr = 1;
3695 break;
3696 }
3697 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3698 crt_path = path;
3699 }
3700
3701 ssl_conf = calloc(1, sizeof *ssl_conf);
3702 cur_arg = ssl_b ? ssl_b : 1;
3703 while (cur_arg < ssl_e) {
3704 newarg = 0;
3705 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3706 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3707 newarg = 1;
3708 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3709 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3710 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3711 args[cur_arg], linenum, file);
3712 cfgerr = 1;
3713 }
3714 cur_arg += 1 + ssl_bind_kws[i].skip;
3715 break;
3716 }
3717 }
3718 if (!cfgerr && !newarg) {
3719 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3720 args[cur_arg], linenum, file);
3721 cfgerr = 1;
3722 break;
3723 }
3724 }
3725 if (cfgerr) {
3726 ssl_sock_free_ssl_conf(ssl_conf);
3727 free(ssl_conf);
3728 ssl_conf = NULL;
3729 break;
3730 }
3731
3732 if (stat(crt_path, &buf) == 0) {
3733 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3734 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003735 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003736 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3737 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003738 }
3739
Willy Tarreauad1731d2013-04-02 17:35:58 +02003740 if (cfgerr) {
3741 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003742 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003743 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003744 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003745 fclose(f);
3746 return cfgerr;
3747}
3748
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003749/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003750static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003751ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003752{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003753 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003754 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003755 SSL_OP_ALL | /* all known workarounds for bugs */
3756 SSL_OP_NO_SSLv2 |
3757 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003758 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003759 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003760 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003761 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003762 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003763 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003764 SSL_MODE_ENABLE_PARTIAL_WRITE |
3765 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003766 SSL_MODE_RELEASE_BUFFERS |
3767 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003768 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003769 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003770 int flags = MC_SSL_O_ALL;
3771 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003772
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003773 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003774 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003775
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003776 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003777 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3778 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3779 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003780 else
3781 flags = conf_ssl_methods->flags;
3782
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003783 min = conf_ssl_methods->min;
3784 max = conf_ssl_methods->max;
3785 /* start with TLSv10 to remove SSLv3 per default */
3786 if (!min && (!max || max >= CONF_TLSV10))
3787 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003788 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003789 if (min)
3790 flags |= (methodVersions[min].flag - 1);
3791 if (max)
3792 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003793 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003794 min = max = CONF_TLSV_NONE;
3795 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003796 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003797 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003798 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003799 if (min) {
3800 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003801 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3802 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3803 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3804 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003805 hole = 0;
3806 }
3807 max = i;
3808 }
3809 else {
3810 min = max = i;
3811 }
3812 }
3813 else {
3814 if (min)
3815 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003816 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003817 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003818 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3819 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003820 cfgerr += 1;
3821 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003822 /* save real min/max in bind_conf */
3823 conf_ssl_methods->min = min;
3824 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003825
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003826#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003827 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003828 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003829 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003830 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003831 else
3832 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3833 if (flags & methodVersions[i].flag)
3834 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003835#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003836 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003837 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3838 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003839#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003840
3841 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3842 options |= SSL_OP_NO_TICKET;
3843 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3844 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3845 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003846
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003847#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003848 if (global_ssl.async)
3849 mode |= SSL_MODE_ASYNC;
3850#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003851 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003852 if (global_ssl.life_time)
3853 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003854
3855#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3856#ifdef OPENSSL_IS_BORINGSSL
3857 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3858 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003859#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3860 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3861 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003862#else
3863 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003864#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003865 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003866#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003867 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003868}
3869
William Lallemand4f45bb92017-10-30 20:08:51 +01003870
3871static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3872{
3873 if (first == block) {
3874 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3875 if (first->len > 0)
3876 sh_ssl_sess_tree_delete(sh_ssl_sess);
3877 }
3878}
3879
3880/* return first block from sh_ssl_sess */
3881static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3882{
3883 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3884
3885}
3886
3887/* store a session into the cache
3888 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3889 * data: asn1 encoded session
3890 * data_len: asn1 encoded session length
3891 * Returns 1 id session was stored (else 0)
3892 */
3893static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3894{
3895 struct shared_block *first;
3896 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3897
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003898 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003899 if (!first) {
3900 /* Could not retrieve enough free blocks to store that session */
3901 return 0;
3902 }
3903
3904 /* STORE the key in the first elem */
3905 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3906 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3907 first->len = sizeof(struct sh_ssl_sess_hdr);
3908
3909 /* it returns the already existing node
3910 or current node if none, never returns null */
3911 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3912 if (oldsh_ssl_sess != sh_ssl_sess) {
3913 /* NOTE: Row couldn't be in use because we lock read & write function */
3914 /* release the reserved row */
3915 shctx_row_dec_hot(ssl_shctx, first);
3916 /* replace the previous session already in the tree */
3917 sh_ssl_sess = oldsh_ssl_sess;
3918 /* ignore the previous session data, only use the header */
3919 first = sh_ssl_sess_first_block(sh_ssl_sess);
3920 shctx_row_inc_hot(ssl_shctx, first);
3921 first->len = sizeof(struct sh_ssl_sess_hdr);
3922 }
3923
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003924 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003925 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003926 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003927 }
3928
3929 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003930
3931 return 1;
3932}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003933
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003934/* SSL callback used when a new session is created while connecting to a server */
3935static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3936{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003937 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003938 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003939
Willy Tarreau07d94e42018-09-20 10:57:52 +02003940 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003941
Olivier Houcharde6060c52017-11-16 17:42:52 +01003942 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3943 int len;
3944 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003945
Olivier Houcharde6060c52017-11-16 17:42:52 +01003946 len = i2d_SSL_SESSION(sess, NULL);
3947 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3948 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3949 } else {
3950 free(s->ssl_ctx.reused_sess[tid].ptr);
3951 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3952 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3953 }
3954 if (s->ssl_ctx.reused_sess[tid].ptr) {
3955 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3956 &ptr);
3957 }
3958 } else {
3959 free(s->ssl_ctx.reused_sess[tid].ptr);
3960 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3961 }
3962
3963 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003964}
3965
Olivier Houcharde6060c52017-11-16 17:42:52 +01003966
William Lallemanded0b5ad2017-10-30 19:36:36 +01003967/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003968int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003969{
3970 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3971 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3972 unsigned char *p;
3973 int data_len;
3974 unsigned int sid_length, sid_ctx_length;
3975 const unsigned char *sid_data;
3976 const unsigned char *sid_ctx_data;
3977
3978 /* Session id is already stored in to key and session id is known
3979 * so we dont store it to keep size.
3980 */
3981
3982 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3983 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3984 SSL_SESSION_set1_id(sess, sid_data, 0);
3985 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3986
3987 /* check if buffer is large enough for the ASN1 encoded session */
3988 data_len = i2d_SSL_SESSION(sess, NULL);
3989 if (data_len > SHSESS_MAX_DATA_LEN)
3990 goto err;
3991
3992 p = encsess;
3993
3994 /* process ASN1 session encoding before the lock */
3995 i2d_SSL_SESSION(sess, &p);
3996
3997 memcpy(encid, sid_data, sid_length);
3998 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3999 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4000
William Lallemanda3c77cf2017-10-30 23:44:40 +01004001 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004002 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004003 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004004 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004005err:
4006 /* reset original length values */
4007 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4008 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4009
4010 return 0; /* do not increment session reference count */
4011}
4012
4013/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004014SSL_SESSION *sh_ssl_sess_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004015{
William Lallemand4f45bb92017-10-30 20:08:51 +01004016 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004017 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4018 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004019 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004020 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004021
4022 global.shctx_lookups++;
4023
4024 /* allow the session to be freed automatically by openssl */
4025 *do_copy = 0;
4026
4027 /* tree key is zeros padded sessionid */
4028 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4029 memcpy(tmpkey, key, key_len);
4030 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4031 key = tmpkey;
4032 }
4033
4034 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004035 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004036
4037 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004038 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4039 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004040 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004041 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004042 global.shctx_misses++;
4043 return NULL;
4044 }
4045
William Lallemand4f45bb92017-10-30 20:08:51 +01004046 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4047 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004048
William Lallemand4f45bb92017-10-30 20:08:51 +01004049 shctx_row_data_get(ssl_shctx, first, data, sizeof(struct sh_ssl_sess_hdr), first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004050
William Lallemanda3c77cf2017-10-30 23:44:40 +01004051 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004052
4053 /* decode ASN1 session */
4054 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004055 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056 /* Reset session id and session id contenxt */
4057 if (sess) {
4058 SSL_SESSION_set1_id(sess, key, key_len);
4059 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4060 }
4061
4062 return sess;
4063}
4064
William Lallemand4f45bb92017-10-30 20:08:51 +01004065
William Lallemanded0b5ad2017-10-30 19:36:36 +01004066/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004067void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004068{
William Lallemand4f45bb92017-10-30 20:08:51 +01004069 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004070 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4071 unsigned int sid_length;
4072 const unsigned char *sid_data;
4073 (void)ctx;
4074
4075 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4076 /* tree key is zeros padded sessionid */
4077 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4078 memcpy(tmpkey, sid_data, sid_length);
4079 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4080 sid_data = tmpkey;
4081 }
4082
William Lallemanda3c77cf2017-10-30 23:44:40 +01004083 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004084
4085 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004086 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4087 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004088 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004089 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004090 }
4091
4092 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004093 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004094}
4095
4096/* Set session cache mode to server and disable openssl internal cache.
4097 * Set shared cache callbacks on an ssl context.
4098 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004099void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004100{
4101 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4102
4103 if (!ssl_shctx) {
4104 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4105 return;
4106 }
4107
4108 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4109 SSL_SESS_CACHE_NO_INTERNAL |
4110 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4111
4112 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004113 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4114 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4115 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004116}
4117
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004118int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4119{
4120 struct proxy *curproxy = bind_conf->frontend;
4121 int cfgerr = 0;
4122 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004123 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004124 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004125#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4126 const char *conf_ciphersuites;
4127#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004128 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004129
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004130 if (ssl_conf) {
4131 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4132 int i, min, max;
4133 int flags = MC_SSL_O_ALL;
4134
4135 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004136 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4137 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004138 if (min)
4139 flags |= (methodVersions[min].flag - 1);
4140 if (max)
4141 flags |= ~((methodVersions[max].flag << 1) - 1);
4142 min = max = CONF_TLSV_NONE;
4143 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4144 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4145 if (min)
4146 max = i;
4147 else
4148 min = max = i;
4149 }
4150 /* save real min/max */
4151 conf_ssl_methods->min = min;
4152 conf_ssl_methods->max = max;
4153 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004154 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4155 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004156 cfgerr += 1;
4157 }
4158 }
4159
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004160 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004161 case SSL_SOCK_VERIFY_NONE:
4162 verify = SSL_VERIFY_NONE;
4163 break;
4164 case SSL_SOCK_VERIFY_OPTIONAL:
4165 verify = SSL_VERIFY_PEER;
4166 break;
4167 case SSL_SOCK_VERIFY_REQUIRED:
4168 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4169 break;
4170 }
4171 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4172 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004173 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4174 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4175 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004176 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004177 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004178 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4179 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004180 cfgerr++;
4181 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004182 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4183 /* set CA names for client cert request, function returns void */
4184 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4185 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004186 }
Emeric Brun850efd52014-01-29 12:24:34 +01004187 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004188 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4189 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004190 cfgerr++;
4191 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004192#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004193 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004194 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4195
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004196 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004197 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4198 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004199 cfgerr++;
4200 }
Emeric Brun561e5742012-10-02 15:20:55 +02004201 else {
4202 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4203 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004204 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004205#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004206 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004207 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004208#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004209 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004210 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004211 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4212 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004213 cfgerr++;
4214 }
4215 }
4216#endif
4217
William Lallemand4f45bb92017-10-30 20:08:51 +01004218 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004219 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4220 if (conf_ciphers &&
4221 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004222 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4223 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004224 cfgerr++;
4225 }
4226
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004227#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4228 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4229 if (conf_ciphersuites &&
4230 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4231 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4232 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4233 cfgerr++;
4234 }
4235#endif
4236
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004237#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004238 /* If tune.ssl.default-dh-param has not been set,
4239 neither has ssl-default-dh-file and no static DH
4240 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004241 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004242 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004243 (ssl_dh_ptr_index == -1 ||
4244 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004245 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4246 const SSL_CIPHER * cipher = NULL;
4247 char cipher_description[128];
4248 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4249 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4250 which is not ephemeral DH. */
4251 const char dhe_description[] = " Kx=DH ";
4252 const char dhe_export_description[] = " Kx=DH(";
4253 int idx = 0;
4254 int dhe_found = 0;
4255 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004256
Remi Gacogne23d5d372014-10-10 17:04:26 +02004257 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004258
Remi Gacogne23d5d372014-10-10 17:04:26 +02004259 if (ssl) {
4260 ciphers = SSL_get_ciphers(ssl);
4261
4262 if (ciphers) {
4263 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4264 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4265 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4266 if (strstr(cipher_description, dhe_description) != NULL ||
4267 strstr(cipher_description, dhe_export_description) != NULL) {
4268 dhe_found = 1;
4269 break;
4270 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004271 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004272 }
4273 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004274 SSL_free(ssl);
4275 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004276 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004277
Lukas Tribus90132722014-08-18 00:56:33 +02004278 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004279 ha_warning("Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.\n");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004280 }
4281
Willy Tarreauef934602016-12-22 23:12:01 +01004282 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004283 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004284
Willy Tarreauef934602016-12-22 23:12:01 +01004285 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004286 if (local_dh_1024 == NULL) {
4287 local_dh_1024 = ssl_get_dh_1024();
4288 }
Willy Tarreauef934602016-12-22 23:12:01 +01004289 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004290 if (local_dh_2048 == NULL) {
4291 local_dh_2048 = ssl_get_dh_2048();
4292 }
Willy Tarreauef934602016-12-22 23:12:01 +01004293 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004294 if (local_dh_4096 == NULL) {
4295 local_dh_4096 = ssl_get_dh_4096();
4296 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004297 }
4298 }
4299 }
4300#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004301
Emeric Brunfc0421f2012-09-07 17:30:07 +02004302 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004303#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004304 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004305#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004306
Bernard Spil13c53f82018-02-15 13:34:58 +01004307#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004308 ssl_conf_cur = NULL;
4309 if (ssl_conf && ssl_conf->npn_str)
4310 ssl_conf_cur = ssl_conf;
4311 else if (bind_conf->ssl_conf.npn_str)
4312 ssl_conf_cur = &bind_conf->ssl_conf;
4313 if (ssl_conf_cur)
4314 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004315#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004316#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004317 ssl_conf_cur = NULL;
4318 if (ssl_conf && ssl_conf->alpn_str)
4319 ssl_conf_cur = ssl_conf;
4320 else if (bind_conf->ssl_conf.alpn_str)
4321 ssl_conf_cur = &bind_conf->ssl_conf;
4322 if (ssl_conf_cur)
4323 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004324#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004325#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4326 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4327 if (conf_curves) {
4328 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004329 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4330 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004331 cfgerr++;
4332 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004333#if defined(SSL_CTX_set_ecdh_auto)
4334 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4335#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004336 }
4337#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004338#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004339 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004340 int i;
4341 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004342#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004343 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004344 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4345 NULL);
4346
4347 if (ecdhe == NULL) {
4348 SSL_CTX_set_dh_auto(ctx, 1);
4349 return cfgerr;
4350 }
4351#else
4352 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4353 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4354 ECDHE_DEFAULT_CURVE);
4355#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004356
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004357 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004358 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004359 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4360 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004361 cfgerr++;
4362 }
4363 else {
4364 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4365 EC_KEY_free(ecdh);
4366 }
4367 }
4368#endif
4369
Emeric Brunfc0421f2012-09-07 17:30:07 +02004370 return cfgerr;
4371}
4372
Evan Broderbe554312013-06-27 00:05:25 -07004373static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4374{
4375 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4376 size_t prefixlen, suffixlen;
4377
4378 /* Trivial case */
4379 if (strcmp(pattern, hostname) == 0)
4380 return 1;
4381
Evan Broderbe554312013-06-27 00:05:25 -07004382 /* The rest of this logic is based on RFC 6125, section 6.4.3
4383 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4384
Emeric Bruna848dae2013-10-08 11:27:28 +02004385 pattern_wildcard = NULL;
4386 pattern_left_label_end = pattern;
4387 while (*pattern_left_label_end != '.') {
4388 switch (*pattern_left_label_end) {
4389 case 0:
4390 /* End of label not found */
4391 return 0;
4392 case '*':
4393 /* If there is more than one wildcards */
4394 if (pattern_wildcard)
4395 return 0;
4396 pattern_wildcard = pattern_left_label_end;
4397 break;
4398 }
4399 pattern_left_label_end++;
4400 }
4401
4402 /* If it's not trivial and there is no wildcard, it can't
4403 * match */
4404 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004405 return 0;
4406
4407 /* Make sure all labels match except the leftmost */
4408 hostname_left_label_end = strchr(hostname, '.');
4409 if (!hostname_left_label_end
4410 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4411 return 0;
4412
4413 /* Make sure the leftmost label of the hostname is long enough
4414 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004415 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004416 return 0;
4417
4418 /* Finally compare the string on either side of the
4419 * wildcard */
4420 prefixlen = pattern_wildcard - pattern;
4421 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004422 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4423 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004424 return 0;
4425
4426 return 1;
4427}
4428
4429static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4430{
4431 SSL *ssl;
4432 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004433 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004434 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004435
4436 int depth;
4437 X509 *cert;
4438 STACK_OF(GENERAL_NAME) *alt_names;
4439 int i;
4440 X509_NAME *cert_subject;
4441 char *str;
4442
4443 if (ok == 0)
4444 return ok;
4445
4446 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004447 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004448
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004449 /* We're checking if the provided hostnames match the desired one. The
4450 * desired hostname comes from the SNI we presented if any, or if not
4451 * provided then it may have been explicitly stated using a "verifyhost"
4452 * directive. If neither is set, we don't care about the name so the
4453 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004454 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004455 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004456 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004457 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004458 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004459 if (!servername)
4460 return ok;
4461 }
Evan Broderbe554312013-06-27 00:05:25 -07004462
4463 /* We only need to verify the CN on the actual server cert,
4464 * not the indirect CAs */
4465 depth = X509_STORE_CTX_get_error_depth(ctx);
4466 if (depth != 0)
4467 return ok;
4468
4469 /* At this point, the cert is *not* OK unless we can find a
4470 * hostname match */
4471 ok = 0;
4472
4473 cert = X509_STORE_CTX_get_current_cert(ctx);
4474 /* It seems like this might happen if verify peer isn't set */
4475 if (!cert)
4476 return ok;
4477
4478 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4479 if (alt_names) {
4480 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4481 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4482 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004483#if OPENSSL_VERSION_NUMBER < 0x00907000L
4484 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4485#else
Evan Broderbe554312013-06-27 00:05:25 -07004486 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004487#endif
Evan Broderbe554312013-06-27 00:05:25 -07004488 ok = ssl_sock_srv_hostcheck(str, servername);
4489 OPENSSL_free(str);
4490 }
4491 }
4492 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004493 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004494 }
4495
4496 cert_subject = X509_get_subject_name(cert);
4497 i = -1;
4498 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4499 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004500 ASN1_STRING *value;
4501 value = X509_NAME_ENTRY_get_data(entry);
4502 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004503 ok = ssl_sock_srv_hostcheck(str, servername);
4504 OPENSSL_free(str);
4505 }
4506 }
4507
Willy Tarreau71d058c2017-07-26 20:09:56 +02004508 /* report the mismatch and indicate if SNI was used or not */
4509 if (!ok && !conn->err_code)
4510 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004511 return ok;
4512}
4513
Emeric Brun94324a42012-10-11 14:00:19 +02004514/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004515int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004516{
Willy Tarreau03209342016-12-22 17:08:28 +01004517 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004518 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004519 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004520 SSL_OP_ALL | /* all known workarounds for bugs */
4521 SSL_OP_NO_SSLv2 |
4522 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004523 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004524 SSL_MODE_ENABLE_PARTIAL_WRITE |
4525 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004526 SSL_MODE_RELEASE_BUFFERS |
4527 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004528 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004529 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004530 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004531 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004532 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004533
Thierry Fournier383085f2013-01-24 14:15:43 +01004534 /* Make sure openssl opens /dev/urandom before the chroot */
4535 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004536 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004537 cfgerr++;
4538 }
4539
Willy Tarreaufce03112015-01-15 21:32:40 +01004540 /* Automatic memory computations need to know we use SSL there */
4541 global.ssl_used_backend = 1;
4542
4543 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004544 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004545 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004546 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4547 curproxy->id, srv->id,
4548 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004549 cfgerr++;
4550 return cfgerr;
4551 }
4552 }
Emeric Brun94324a42012-10-11 14:00:19 +02004553 if (srv->use_ssl)
4554 srv->xprt = &ssl_sock;
4555 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004556 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004557
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004558 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004559 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004560 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4561 proxy_type_str(curproxy), curproxy->id,
4562 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004563 cfgerr++;
4564 return cfgerr;
4565 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004566
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004567 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004568 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4569 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4570 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004571 else
4572 flags = conf_ssl_methods->flags;
4573
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004574 /* Real min and max should be determinate with configuration and openssl's capabilities */
4575 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004576 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004577 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004578 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004579
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004580 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004581 min = max = CONF_TLSV_NONE;
4582 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004583 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004584 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004585 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004586 if (min) {
4587 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004588 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4589 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4590 proxy_type_str(curproxy), curproxy->id, srv->id,
4591 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004592 hole = 0;
4593 }
4594 max = i;
4595 }
4596 else {
4597 min = max = i;
4598 }
4599 }
4600 else {
4601 if (min)
4602 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004603 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004604 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004605 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4606 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004607 cfgerr += 1;
4608 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004609
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004610#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004611 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004612 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004613 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004614 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004615 else
4616 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4617 if (flags & methodVersions[i].flag)
4618 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004619#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004620 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004621 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4622 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004623#endif
4624
4625 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4626 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004627 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004628
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004629#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004630 if (global_ssl.async)
4631 mode |= SSL_MODE_ASYNC;
4632#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004633 SSL_CTX_set_mode(ctx, mode);
4634 srv->ssl_ctx.ctx = ctx;
4635
Emeric Bruna7aa3092012-10-26 12:58:00 +02004636 if (srv->ssl_ctx.client_crt) {
4637 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004638 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4639 proxy_type_str(curproxy), curproxy->id,
4640 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004641 cfgerr++;
4642 }
4643 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004644 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4645 proxy_type_str(curproxy), curproxy->id,
4646 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004647 cfgerr++;
4648 }
4649 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004650 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4651 proxy_type_str(curproxy), curproxy->id,
4652 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004653 cfgerr++;
4654 }
4655 }
Emeric Brun94324a42012-10-11 14:00:19 +02004656
Emeric Brun850efd52014-01-29 12:24:34 +01004657 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4658 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004659 switch (srv->ssl_ctx.verify) {
4660 case SSL_SOCK_VERIFY_NONE:
4661 verify = SSL_VERIFY_NONE;
4662 break;
4663 case SSL_SOCK_VERIFY_REQUIRED:
4664 verify = SSL_VERIFY_PEER;
4665 break;
4666 }
Evan Broderbe554312013-06-27 00:05:25 -07004667 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004668 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004669 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004670 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004671 if (srv->ssl_ctx.ca_file) {
4672 /* load CAfile to verify */
4673 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004674 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4675 curproxy->id, srv->id,
4676 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004677 cfgerr++;
4678 }
4679 }
Emeric Brun850efd52014-01-29 12:24:34 +01004680 else {
4681 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004682 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
4683 curproxy->id, srv->id,
4684 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004685 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004686 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4687 curproxy->id, srv->id,
4688 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004689 cfgerr++;
4690 }
Emeric Brunef42d922012-10-11 16:11:36 +02004691#ifdef X509_V_FLAG_CRL_CHECK
4692 if (srv->ssl_ctx.crl_file) {
4693 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4694
4695 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004696 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4697 curproxy->id, srv->id,
4698 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004699 cfgerr++;
4700 }
4701 else {
4702 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4703 }
4704 }
4705#endif
4706 }
4707
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004708 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4709 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4710 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004711 if (srv->ssl_ctx.ciphers &&
4712 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004713 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4714 curproxy->id, srv->id,
4715 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004716 cfgerr++;
4717 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004718
4719#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4720 if (srv->ssl_ctx.ciphersuites &&
4721 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4722 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4723 curproxy->id, srv->id,
4724 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4725 cfgerr++;
4726 }
4727#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004728#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4729 if (srv->ssl_ctx.npn_str)
4730 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4731#endif
4732#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4733 if (srv->ssl_ctx.alpn_str)
4734 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4735#endif
4736
Emeric Brun94324a42012-10-11 14:00:19 +02004737
4738 return cfgerr;
4739}
4740
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004741/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004742 * be NULL, in which case nothing is done. Returns the number of errors
4743 * encountered.
4744 */
Willy Tarreau03209342016-12-22 17:08:28 +01004745int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004746{
4747 struct ebmb_node *node;
4748 struct sni_ctx *sni;
4749 int err = 0;
4750
Willy Tarreaufce03112015-01-15 21:32:40 +01004751 /* Automatic memory computations need to know we use SSL there */
4752 global.ssl_used_frontend = 1;
4753
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004754 /* Make sure openssl opens /dev/urandom before the chroot */
4755 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004756 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004757 err++;
4758 }
4759 /* Create initial_ctx used to start the ssl connection before do switchctx */
4760 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004761 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004762 /* It should not be necessary to call this function, but it's
4763 necessary first to check and move all initialisation related
4764 to initial_ctx in ssl_sock_initial_ctx. */
4765 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4766 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004767 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004768 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004769
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004770 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004771 while (node) {
4772 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004773 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4774 /* only initialize the CTX on its first occurrence and
4775 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004776 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004777 node = ebmb_next(node);
4778 }
4779
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004780 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004781 while (node) {
4782 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004783 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4784 /* only initialize the CTX on its first occurrence and
4785 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004786 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004787 node = ebmb_next(node);
4788 }
4789 return err;
4790}
4791
Willy Tarreau55d37912016-12-21 23:38:39 +01004792/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4793 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4794 * alerts are directly emitted since the rest of the stack does it below.
4795 */
4796int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4797{
4798 struct proxy *px = bind_conf->frontend;
4799 int alloc_ctx;
4800 int err;
4801
4802 if (!bind_conf->is_ssl) {
4803 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004804 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4805 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004806 }
4807 return 0;
4808 }
4809 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004810 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004811 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4812 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004813 }
4814 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004815 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4816 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004817 return -1;
4818 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004819 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004820 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004821 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004822 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004823 sizeof(*sh_ssl_sess_tree),
4824 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004825 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004826 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4827 ha_alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
4828 else
4829 ha_alert("Unable to allocate SSL session cache.\n");
4830 return -1;
4831 }
4832 /* free block callback */
4833 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4834 /* init the root tree within the extra space */
4835 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4836 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004837 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004838 err = 0;
4839 /* initialize all certificate contexts */
4840 err += ssl_sock_prepare_all_ctx(bind_conf);
4841
4842 /* initialize CA variables if the certificates generation is enabled */
4843 err += ssl_sock_load_ca(bind_conf);
4844
4845 return -err;
4846}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004847
4848/* release ssl context allocated for servers. */
4849void ssl_sock_free_srv_ctx(struct server *srv)
4850{
Olivier Houchardc7566002018-11-20 23:33:50 +01004851#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4852 if (srv->ssl_ctx.alpn_str)
4853 free(srv->ssl_ctx.alpn_str);
4854#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004855#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004856 if (srv->ssl_ctx.npn_str)
4857 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01004858#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004859 if (srv->ssl_ctx.ctx)
4860 SSL_CTX_free(srv->ssl_ctx.ctx);
4861}
4862
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004863/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004864 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4865 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004866void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004867{
4868 struct ebmb_node *node, *back;
4869 struct sni_ctx *sni;
4870
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004871 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004872 while (node) {
4873 sni = ebmb_entry(node, struct sni_ctx, name);
4874 back = ebmb_next(node);
4875 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004876 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004877 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004878 ssl_sock_free_ssl_conf(sni->conf);
4879 free(sni->conf);
4880 sni->conf = NULL;
4881 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004882 free(sni);
4883 node = back;
4884 }
4885
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004886 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004887 while (node) {
4888 sni = ebmb_entry(node, struct sni_ctx, name);
4889 back = ebmb_next(node);
4890 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004891 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004892 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004893 ssl_sock_free_ssl_conf(sni->conf);
4894 free(sni->conf);
4895 sni->conf = NULL;
4896 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004897 free(sni);
4898 node = back;
4899 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004900 SSL_CTX_free(bind_conf->initial_ctx);
4901 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004902 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004903 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004904}
4905
Willy Tarreau795cdab2016-12-22 17:30:54 +01004906/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4907void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4908{
4909 ssl_sock_free_ca(bind_conf);
4910 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004911 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004912 free(bind_conf->ca_sign_file);
4913 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004914 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004915 free(bind_conf->keys_ref->filename);
4916 free(bind_conf->keys_ref->tlskeys);
4917 LIST_DEL(&bind_conf->keys_ref->list);
4918 free(bind_conf->keys_ref);
4919 }
4920 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004921 bind_conf->ca_sign_pass = NULL;
4922 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004923}
4924
Christopher Faulet31af49d2015-06-09 17:29:50 +02004925/* Load CA cert file and private key used to generate certificates */
4926int
Willy Tarreau03209342016-12-22 17:08:28 +01004927ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004928{
Willy Tarreau03209342016-12-22 17:08:28 +01004929 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004930 FILE *fp;
4931 X509 *cacert = NULL;
4932 EVP_PKEY *capkey = NULL;
4933 int err = 0;
4934
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004935 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004936 return err;
4937
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004938#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004939 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004940 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004941 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004942 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004943 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004944#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004945
Christopher Faulet31af49d2015-06-09 17:29:50 +02004946 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004947 ha_alert("Proxy '%s': cannot enable certificate generation, "
4948 "no CA certificate File configured at [%s:%d].\n",
4949 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004950 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004951 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004952
4953 /* read in the CA certificate */
4954 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004955 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4956 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004957 goto load_error;
4958 }
4959 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004960 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4961 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004962 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004963 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004964 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004965 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004966 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4967 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004968 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004969 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004970
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004971 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004972 bind_conf->ca_sign_cert = cacert;
4973 bind_conf->ca_sign_pkey = capkey;
4974 return err;
4975
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004976 read_error:
4977 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004978 if (capkey) EVP_PKEY_free(capkey);
4979 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004980 load_error:
4981 bind_conf->generate_certs = 0;
4982 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004983 return err;
4984}
4985
4986/* Release CA cert and private key used to generate certificated */
4987void
4988ssl_sock_free_ca(struct bind_conf *bind_conf)
4989{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004990 if (bind_conf->ca_sign_pkey)
4991 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4992 if (bind_conf->ca_sign_cert)
4993 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004994 bind_conf->ca_sign_pkey = NULL;
4995 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004996}
4997
Emeric Brun46591952012-05-18 15:47:34 +02004998/*
4999 * This function is called if SSL * context is not yet allocated. The function
5000 * is designed to be called before any other data-layer operation and sets the
5001 * handshake flag on the connection. It is safe to call it multiple times.
5002 * It returns 0 on success and -1 in error case.
5003 */
5004static int ssl_sock_init(struct connection *conn)
5005{
5006 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005007 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005008 return 0;
5009
Willy Tarreau3c728722014-01-23 13:50:42 +01005010 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005011 return 0;
5012
Willy Tarreau20879a02012-12-03 16:32:10 +01005013 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5014 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005015 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005016 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005017
Emeric Brun46591952012-05-18 15:47:34 +02005018 /* If it is in client mode initiate SSL session
5019 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005020 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005021 int may_retry = 1;
5022
5023 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005024 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005025 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005026 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005027 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005028 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005029 goto retry_connect;
5030 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005031 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005032 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005033 }
Emeric Brun46591952012-05-18 15:47:34 +02005034
Emeric Brun46591952012-05-18 15:47:34 +02005035 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005036 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005037 SSL_free(conn->xprt_ctx);
5038 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005039 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005040 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005041 goto retry_connect;
5042 }
Emeric Brun55476152014-11-12 17:35:37 +01005043 conn->err_code = CO_ER_SSL_NO_MEM;
5044 return -1;
5045 }
Emeric Brun46591952012-05-18 15:47:34 +02005046
Evan Broderbe554312013-06-27 00:05:25 -07005047 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005048 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005049 SSL_free(conn->xprt_ctx);
5050 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005051 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005052 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005053 goto retry_connect;
5054 }
Emeric Brun55476152014-11-12 17:35:37 +01005055 conn->err_code = CO_ER_SSL_NO_MEM;
5056 return -1;
5057 }
5058
5059 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005060 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5061 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5062 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5063 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005064 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005065 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5066 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005067 } else if (sess) {
5068 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005069 }
5070 }
Evan Broderbe554312013-06-27 00:05:25 -07005071
Emeric Brun46591952012-05-18 15:47:34 +02005072 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005073 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005074
Emeric Brun7ad43e72018-10-10 14:51:02 +02005075 HA_ATOMIC_ADD(&sslconns, 1);
5076 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005077 return 0;
5078 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005079 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005080 int may_retry = 1;
5081
5082 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005083 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005084 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005085 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005086 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005087 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005088 goto retry_accept;
5089 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005090 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005091 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005092 }
Emeric Brun46591952012-05-18 15:47:34 +02005093
Emeric Brun46591952012-05-18 15:47:34 +02005094 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005095 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005096 SSL_free(conn->xprt_ctx);
5097 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005098 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005099 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005100 goto retry_accept;
5101 }
Emeric Brun55476152014-11-12 17:35:37 +01005102 conn->err_code = CO_ER_SSL_NO_MEM;
5103 return -1;
5104 }
Emeric Brun46591952012-05-18 15:47:34 +02005105
Emeric Brune1f38db2012-09-03 20:36:47 +02005106 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005107 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005108 SSL_free(conn->xprt_ctx);
5109 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005110 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005111 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005112 goto retry_accept;
5113 }
Emeric Brun55476152014-11-12 17:35:37 +01005114 conn->err_code = CO_ER_SSL_NO_MEM;
5115 return -1;
5116 }
5117
5118 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005119
Emeric Brun46591952012-05-18 15:47:34 +02005120 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005121 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005122#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005123 conn->flags |= CO_FL_EARLY_SSL_HS;
5124#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005125
Emeric Brun7ad43e72018-10-10 14:51:02 +02005126 HA_ATOMIC_ADD(&sslconns, 1);
5127 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005128 return 0;
5129 }
5130 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005131 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005132 return -1;
5133}
5134
5135
5136/* This is the callback which is used when an SSL handshake is pending. It
5137 * updates the FD status if it wants some polling before being called again.
5138 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5139 * otherwise it returns non-zero and removes itself from the connection's
5140 * flags (the bit is provided in <flag> by the caller).
5141 */
5142int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5143{
5144 int ret;
5145
Willy Tarreau3c728722014-01-23 13:50:42 +01005146 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005147 return 0;
5148
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005149 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005150 goto out_error;
5151
Olivier Houchardc2aae742017-09-22 18:26:28 +02005152#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5153 /*
5154 * Check if we have early data. If we do, we have to read them
5155 * before SSL_do_handshake() is called, And there's no way to
5156 * detect early data, except to try to read them
5157 */
5158 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5159 size_t read_data;
5160
5161 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5162 1, &read_data);
5163 if (ret == SSL_READ_EARLY_DATA_ERROR)
5164 goto check_error;
5165 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5166 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5167 return 1;
5168 } else
5169 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5170 }
5171#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005172 /* If we use SSL_do_handshake to process a reneg initiated by
5173 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5174 * Usually SSL_write and SSL_read are used and process implicitly
5175 * the reneg handshake.
5176 * Here we use SSL_peek as a workaround for reneg.
5177 */
5178 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5179 char c;
5180
5181 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5182 if (ret <= 0) {
5183 /* handshake may have not been completed, let's find why */
5184 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005185
Emeric Brun674b7432012-11-08 19:21:55 +01005186 if (ret == SSL_ERROR_WANT_WRITE) {
5187 /* SSL handshake needs to write, L4 connection may not be ready */
5188 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005189 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005190 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005191 return 0;
5192 }
5193 else if (ret == SSL_ERROR_WANT_READ) {
5194 /* handshake may have been completed but we have
5195 * no more data to read.
5196 */
5197 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5198 ret = 1;
5199 goto reneg_ok;
5200 }
5201 /* SSL handshake needs to read, L4 connection is ready */
5202 if (conn->flags & CO_FL_WAIT_L4_CONN)
5203 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5204 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005205 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005206 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005207 return 0;
5208 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005209#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005210 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005211 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005212 return 0;
5213 }
5214#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005215 else if (ret == SSL_ERROR_SYSCALL) {
5216 /* if errno is null, then connection was successfully established */
5217 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5218 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005219 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005220#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005221 conn->err_code = CO_ER_SSL_HANDSHAKE;
5222#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005223 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005224#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005225 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5226 empty_handshake = state == TLS_ST_BEFORE;
5227#else
5228 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5229#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005230 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005231 if (!errno) {
5232 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5233 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5234 else
5235 conn->err_code = CO_ER_SSL_EMPTY;
5236 }
5237 else {
5238 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5239 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5240 else
5241 conn->err_code = CO_ER_SSL_ABORT;
5242 }
5243 }
5244 else {
5245 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5246 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005247 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005248 conn->err_code = CO_ER_SSL_HANDSHAKE;
5249 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005250#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005251 }
Emeric Brun674b7432012-11-08 19:21:55 +01005252 goto out_error;
5253 }
5254 else {
5255 /* Fail on all other handshake errors */
5256 /* Note: OpenSSL may leave unread bytes in the socket's
5257 * buffer, causing an RST to be emitted upon close() on
5258 * TCP sockets. We first try to drain possibly pending
5259 * data to avoid this as much as possible.
5260 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005261 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005262 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005263 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5264 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005265 goto out_error;
5266 }
5267 }
5268 /* read some data: consider handshake completed */
5269 goto reneg_ok;
5270 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005271 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005272check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005273 if (ret != 1) {
5274 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005275 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005276
5277 if (ret == SSL_ERROR_WANT_WRITE) {
5278 /* SSL handshake needs to write, L4 connection may not be ready */
5279 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005280 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005281 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005282 return 0;
5283 }
5284 else if (ret == SSL_ERROR_WANT_READ) {
5285 /* SSL handshake needs to read, L4 connection is ready */
5286 if (conn->flags & CO_FL_WAIT_L4_CONN)
5287 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5288 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005289 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005290 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005291 return 0;
5292 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005293#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005294 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005295 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005296 return 0;
5297 }
5298#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005299 else if (ret == SSL_ERROR_SYSCALL) {
5300 /* if errno is null, then connection was successfully established */
5301 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5302 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005303 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005304#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005305 conn->err_code = CO_ER_SSL_HANDSHAKE;
5306#else
5307 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005308#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005309 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5310 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005311#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005312 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005313#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005314 if (empty_handshake) {
5315 if (!errno) {
5316 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5317 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5318 else
5319 conn->err_code = CO_ER_SSL_EMPTY;
5320 }
5321 else {
5322 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5323 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5324 else
5325 conn->err_code = CO_ER_SSL_ABORT;
5326 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005327 }
5328 else {
5329 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5330 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5331 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005332 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005333 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005334#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005335 }
Willy Tarreau89230192012-09-28 20:22:13 +02005336 goto out_error;
5337 }
Emeric Brun46591952012-05-18 15:47:34 +02005338 else {
5339 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005340 /* Note: OpenSSL may leave unread bytes in the socket's
5341 * buffer, causing an RST to be emitted upon close() on
5342 * TCP sockets. We first try to drain possibly pending
5343 * data to avoid this as much as possible.
5344 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005345 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005346 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005347 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5348 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005349 goto out_error;
5350 }
5351 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005352#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5353 else {
5354 /*
5355 * If the server refused the early data, we have to send a
5356 * 425 to the client, as we no longer have the data to sent
5357 * them again.
5358 */
5359 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5360 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5361 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5362 goto out_error;
5363 }
5364 }
5365 }
5366#endif
5367
Emeric Brun46591952012-05-18 15:47:34 +02005368
Emeric Brun674b7432012-11-08 19:21:55 +01005369reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005370
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005371#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005372 /* ASYNC engine API doesn't support moving read/write
5373 * buffers. So we disable ASYNC mode right after
5374 * the handshake to avoid buffer oveflows.
5375 */
5376 if (global_ssl.async)
5377 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5378#endif
Emeric Brun46591952012-05-18 15:47:34 +02005379 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005380 if (!SSL_session_reused(conn->xprt_ctx)) {
5381 if (objt_server(conn->target)) {
5382 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5383 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5384 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005385 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005386 else {
5387 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5388 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5389 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5390 }
Emeric Brun46591952012-05-18 15:47:34 +02005391 }
5392
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005393#ifdef OPENSSL_IS_BORINGSSL
5394 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5395 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5396#endif
Emeric Brun46591952012-05-18 15:47:34 +02005397 /* The connection is now established at both layers, it's time to leave */
5398 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5399 return 1;
5400
5401 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005402 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005403 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005404 ERR_clear_error();
5405
Emeric Brun9fa89732012-10-04 17:09:56 +02005406 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005407 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5408 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5409 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005410 }
5411
Emeric Brun46591952012-05-18 15:47:34 +02005412 /* Fail on all other handshake errors */
5413 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005414 if (!conn->err_code)
5415 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005416 return 0;
5417}
5418
5419/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005420 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005421 * buffer wraps, in which case a second call may be performed. The connection's
5422 * flags are updated with whatever special event is detected (error, read0,
5423 * empty). The caller is responsible for taking care of those events and
5424 * avoiding the call if inappropriate. The function does not call the
5425 * connection's polling update function, so the caller is responsible for this.
5426 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005427static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005428{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005429 ssize_t ret;
5430 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005431
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005432 conn_refresh_polling_flags(conn);
5433
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005434 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005435 goto out_error;
5436
5437 if (conn->flags & CO_FL_HANDSHAKE)
5438 /* a handshake was requested */
5439 return 0;
5440
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005441 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005442
5443 /* read the largest possible block. For this, we perform only one call
5444 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5445 * in which case we accept to do it once again. A new attempt is made on
5446 * EINTR too.
5447 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005448 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005449 int need_out = 0;
5450
Willy Tarreau591d4452018-06-15 17:21:00 +02005451 try = b_contig_space(buf);
5452 if (!try)
5453 break;
5454
Willy Tarreauabf08d92014-01-14 11:31:27 +01005455 if (try > count)
5456 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005457
Olivier Houchardc2aae742017-09-22 18:26:28 +02005458 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5459 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005460 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005461 done++;
5462 try--;
5463 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005464 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005465 conn->tmp_early_data = -1;
5466 continue;
5467 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005468
Olivier Houchardc2aae742017-09-22 18:26:28 +02005469#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5470 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5471 size_t read_length;
5472
5473 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005474 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005475 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5476 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005477 conn->flags |= CO_FL_EARLY_DATA;
5478 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5479 ret == SSL_READ_EARLY_DATA_FINISH) {
5480 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5481 /*
5482 * We're done reading the early data,
5483 * let's make the handshake
5484 */
5485 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5486 conn->flags |= CO_FL_SSL_WAIT_HS;
5487 need_out = 1;
5488 if (read_length == 0)
5489 break;
5490 }
5491 ret = read_length;
5492 }
5493 } else
5494#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005495 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005496#ifdef OPENSSL_IS_BORINGSSL
5497 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5498 if (SSL_in_early_data(conn->xprt_ctx)) {
5499 if (ret > 0)
5500 conn->flags |= CO_FL_EARLY_DATA;
5501 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005502 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005503 }
5504 }
5505#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005506 if (conn->flags & CO_FL_ERROR) {
5507 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005508 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005509 }
Emeric Brun46591952012-05-18 15:47:34 +02005510 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005511 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005512 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005513 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005514 }
Emeric Brun46591952012-05-18 15:47:34 +02005515 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005516 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005517 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005518 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005519 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005520 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005521#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005522 /* Async mode can be re-enabled, because we're leaving data state.*/
5523 if (global_ssl.async)
5524 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5525#endif
Emeric Brun46591952012-05-18 15:47:34 +02005526 break;
5527 }
5528 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005529 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5530 /* handshake is running, and it may need to re-enable read */
5531 conn->flags |= CO_FL_SSL_WAIT_HS;
5532 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005533#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005534 /* Async mode can be re-enabled, because we're leaving data state.*/
5535 if (global_ssl.async)
5536 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5537#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005538 break;
5539 }
Emeric Brun46591952012-05-18 15:47:34 +02005540 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005541 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005542 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005543 } else if (ret == SSL_ERROR_ZERO_RETURN)
5544 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005545 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5546 * stack before shutting down the connection for
5547 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005548 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5549 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005550 /* otherwise it's a real error */
5551 goto out_error;
5552 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005553 if (need_out)
5554 break;
Emeric Brun46591952012-05-18 15:47:34 +02005555 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005556 leave:
5557 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005558 return done;
5559
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005560 clear_ssl_error:
5561 /* Clear openssl global errors stack */
5562 ssl_sock_dump_errors(conn);
5563 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005564 read0:
5565 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005566 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005567
Emeric Brun46591952012-05-18 15:47:34 +02005568 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005569 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005570 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005571 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005572 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005573 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005574}
5575
5576
Willy Tarreau787db9a2018-06-14 18:31:46 +02005577/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5578 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5579 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005580 * Only one call to send() is performed, unless the buffer wraps, in which case
5581 * a second call may be performed. The connection's flags are updated with
5582 * whatever special event is detected (error, empty). The caller is responsible
5583 * for taking care of those events and avoiding the call if inappropriate. The
5584 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005585 * is responsible for this. The buffer's output is not adjusted, it's up to the
5586 * caller to take care of this. It's up to the caller to update the buffer's
5587 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005588 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005589static 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 +02005590{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005591 ssize_t ret;
5592 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005593
5594 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005595 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005596
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005597 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005598 goto out_error;
5599
5600 if (conn->flags & CO_FL_HANDSHAKE)
5601 /* a handshake was requested */
5602 return 0;
5603
5604 /* send the largest possible block. For this we perform only one call
5605 * to send() unless the buffer wraps and we exactly fill the first hunk,
5606 * in which case we accept to do it once again.
5607 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005608 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005609#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5610 size_t written_data;
5611#endif
5612
Willy Tarreau787db9a2018-06-14 18:31:46 +02005613 try = b_contig_data(buf, done);
5614 if (try > count)
5615 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005616
Willy Tarreau7bed9452014-02-02 02:00:24 +01005617 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005618 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005619 global_ssl.max_record && try > global_ssl.max_record) {
5620 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005621 }
5622 else {
5623 /* we need to keep the information about the fact that
5624 * we're not limiting the upcoming send(), because if it
5625 * fails, we'll have to retry with at least as many data.
5626 */
5627 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5628 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005629
Olivier Houchardc2aae742017-09-22 18:26:28 +02005630#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5631 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5632 unsigned int max_early;
5633
Olivier Houchard522eea72017-11-03 16:27:47 +01005634 if (objt_listener(conn->target))
5635 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5636 else {
5637 if (SSL_get0_session(conn->xprt_ctx))
5638 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5639 else
5640 max_early = 0;
5641 }
5642
Olivier Houchard90084a12017-11-23 18:21:29 +01005643 if (try + conn->sent_early_data > max_early) {
5644 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005645 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005646 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5647 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005648 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005649 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005650 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005651 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005652 if (ret == 1) {
5653 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005654 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005655 if (objt_server(conn->target)) {
5656 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5657 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5658 }
5659
Olivier Houchardc2aae742017-09-22 18:26:28 +02005660 }
5661
5662 } else
5663#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005664 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005665
Emeric Brune1f38db2012-09-03 20:36:47 +02005666 if (conn->flags & CO_FL_ERROR) {
5667 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005668 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005669 }
Emeric Brun46591952012-05-18 15:47:34 +02005670 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005671 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005672 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005673 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005674 }
5675 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005676 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005677
Emeric Brun46591952012-05-18 15:47:34 +02005678 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005679 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5680 /* handshake is running, and it may need to re-enable write */
5681 conn->flags |= CO_FL_SSL_WAIT_HS;
5682 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005683#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005684 /* Async mode can be re-enabled, because we're leaving data state.*/
5685 if (global_ssl.async)
5686 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5687#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005688 break;
5689 }
Emeric Brun46591952012-05-18 15:47:34 +02005690 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005691 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005692 break;
5693 }
5694 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005695 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005696 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005697 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005698#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005699 /* Async mode can be re-enabled, because we're leaving data state.*/
5700 if (global_ssl.async)
5701 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5702#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005703 break;
5704 }
Emeric Brun46591952012-05-18 15:47:34 +02005705 goto out_error;
5706 }
5707 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005708 leave:
5709 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005710 return done;
5711
5712 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005713 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005714 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005715 ERR_clear_error();
5716
Emeric Brun46591952012-05-18 15:47:34 +02005717 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005718 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005719}
5720
Emeric Brun46591952012-05-18 15:47:34 +02005721static void ssl_sock_close(struct connection *conn) {
5722
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005723 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005724#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005725 if (global_ssl.async) {
5726 OSSL_ASYNC_FD all_fd[32], afd;
5727 size_t num_all_fds = 0;
5728 int i;
5729
5730 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5731 if (num_all_fds > 32) {
5732 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5733 return;
5734 }
5735
5736 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5737
5738 /* If an async job is pending, we must try to
5739 to catch the end using polling before calling
5740 SSL_free */
5741 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5742 for (i=0 ; i < num_all_fds ; i++) {
5743 /* switch on an handler designed to
5744 * handle the SSL_free
5745 */
5746 afd = all_fd[i];
5747 fdtab[afd].iocb = ssl_async_fd_free;
5748 fdtab[afd].owner = conn->xprt_ctx;
5749 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005750 /* To ensure that the fd cache won't be used
5751 * and we'll catch a real RD event.
5752 */
5753 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005754 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005755 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005756 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005757 return;
5758 }
Emeric Brun3854e012017-05-17 20:42:48 +02005759 /* Else we can remove the fds from the fdtab
5760 * and call SSL_free.
5761 * note: we do a fd_remove and not a delete
5762 * because the fd is owned by the engine.
5763 * the engine is responsible to close
5764 */
5765 for (i=0 ; i < num_all_fds ; i++)
5766 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005767 }
5768#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005769 SSL_free(conn->xprt_ctx);
5770 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005771 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005772 }
Emeric Brun46591952012-05-18 15:47:34 +02005773}
5774
5775/* This function tries to perform a clean shutdown on an SSL connection, and in
5776 * any case, flags the connection as reusable if no handshake was in progress.
5777 */
5778static void ssl_sock_shutw(struct connection *conn, int clean)
5779{
5780 if (conn->flags & CO_FL_HANDSHAKE)
5781 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005782 if (!clean)
5783 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005784 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005785 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005786 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005787 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005788 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005789 ERR_clear_error();
5790 }
Emeric Brun46591952012-05-18 15:47:34 +02005791}
5792
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005793/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005794int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005795{
5796 struct pkey_info *pkinfo;
5797 int bits = 0;
5798 int sig = TLSEXT_signature_anonymous;
5799 int len = -1;
5800
5801 if (!ssl_sock_is_ssl(conn))
5802 return 0;
5803
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005804 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005805 if (pkinfo) {
5806 sig = pkinfo->sig;
5807 bits = pkinfo->bits;
5808 } else {
5809 /* multicert and generated cert have no pkey info */
5810 X509 *crt;
5811 EVP_PKEY *pkey;
5812 crt = SSL_get_certificate(conn->xprt_ctx);
5813 if (!crt)
5814 return 0;
5815 pkey = X509_get_pubkey(crt);
5816 if (pkey) {
5817 bits = EVP_PKEY_bits(pkey);
5818 switch(EVP_PKEY_base_id(pkey)) {
5819 case EVP_PKEY_RSA:
5820 sig = TLSEXT_signature_rsa;
5821 break;
5822 case EVP_PKEY_EC:
5823 sig = TLSEXT_signature_ecdsa;
5824 break;
5825 case EVP_PKEY_DSA:
5826 sig = TLSEXT_signature_dsa;
5827 break;
5828 }
5829 EVP_PKEY_free(pkey);
5830 }
5831 }
5832
5833 switch(sig) {
5834 case TLSEXT_signature_rsa:
5835 len = chunk_printf(out, "RSA%d", bits);
5836 break;
5837 case TLSEXT_signature_ecdsa:
5838 len = chunk_printf(out, "EC%d", bits);
5839 break;
5840 case TLSEXT_signature_dsa:
5841 len = chunk_printf(out, "DSA%d", bits);
5842 break;
5843 default:
5844 return 0;
5845 }
5846 if (len < 0)
5847 return 0;
5848 return 1;
5849}
5850
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005851/* used for ppv2 cert signature (can be used for logging) */
5852const char *ssl_sock_get_cert_sig(struct connection *conn)
5853{
5854 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5855 X509 *crt;
5856
5857 if (!ssl_sock_is_ssl(conn))
5858 return NULL;
5859 crt = SSL_get_certificate(conn->xprt_ctx);
5860 if (!crt)
5861 return NULL;
5862 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5863 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5864}
5865
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005866/* used for ppv2 authority */
5867const char *ssl_sock_get_sni(struct connection *conn)
5868{
5869#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5870 if (!ssl_sock_is_ssl(conn))
5871 return NULL;
5872 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5873#else
5874 return 0;
5875#endif
5876}
5877
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005878/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005879const char *ssl_sock_get_cipher_name(struct connection *conn)
5880{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005881 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005882 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005883
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005884 return SSL_get_cipher_name(conn->xprt_ctx);
5885}
5886
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005887/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005888const char *ssl_sock_get_proto_version(struct connection *conn)
5889{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005890 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005891 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005892
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005893 return SSL_get_version(conn->xprt_ctx);
5894}
5895
Willy Tarreau8d598402012-10-22 17:58:39 +02005896/* Extract a serial from a cert, and copy it to a chunk.
5897 * Returns 1 if serial is found and copied, 0 if no serial found and
5898 * -1 if output is not large enough.
5899 */
5900static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005901ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005902{
5903 ASN1_INTEGER *serial;
5904
5905 serial = X509_get_serialNumber(crt);
5906 if (!serial)
5907 return 0;
5908
5909 if (out->size < serial->length)
5910 return -1;
5911
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005912 memcpy(out->area, serial->data, serial->length);
5913 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005914 return 1;
5915}
5916
Emeric Brun43e79582014-10-29 19:03:26 +01005917/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005918 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5919 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005920 */
5921static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005922ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005923{
5924 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005925 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005926
5927 len =i2d_X509(crt, NULL);
5928 if (len <= 0)
5929 return 1;
5930
5931 if (out->size < len)
5932 return -1;
5933
5934 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005935 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005936 return 1;
5937}
5938
Emeric Brunce5ad802012-10-22 14:11:22 +02005939
Willy Tarreau83061a82018-07-13 11:56:34 +02005940/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005941 * Returns 1 if serial is found and copied, 0 if no valid time found
5942 * and -1 if output is not large enough.
5943 */
5944static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005945ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005946{
5947 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5948 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5949
5950 if (gentm->length < 12)
5951 return 0;
5952 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5953 return 0;
5954 if (out->size < gentm->length-2)
5955 return -1;
5956
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005957 memcpy(out->area, gentm->data+2, gentm->length-2);
5958 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005959 return 1;
5960 }
5961 else if (tm->type == V_ASN1_UTCTIME) {
5962 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5963
5964 if (utctm->length < 10)
5965 return 0;
5966 if (utctm->data[0] >= 0x35)
5967 return 0;
5968 if (out->size < utctm->length)
5969 return -1;
5970
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005971 memcpy(out->area, utctm->data, utctm->length);
5972 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005973 return 1;
5974 }
5975
5976 return 0;
5977}
5978
Emeric Brun87855892012-10-17 17:39:35 +02005979/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5980 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5981 */
5982static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005983ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5984 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005985{
5986 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005987 ASN1_OBJECT *obj;
5988 ASN1_STRING *data;
5989 const unsigned char *data_ptr;
5990 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005991 int i, j, n;
5992 int cur = 0;
5993 const char *s;
5994 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005995 int name_count;
5996
5997 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005998
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005999 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006000 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006001 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006002 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006003 else
6004 j = i;
6005
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006006 ne = X509_NAME_get_entry(a, j);
6007 obj = X509_NAME_ENTRY_get_object(ne);
6008 data = X509_NAME_ENTRY_get_data(ne);
6009 data_ptr = ASN1_STRING_get0_data(data);
6010 data_len = ASN1_STRING_length(data);
6011 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006012 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006013 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006014 s = tmp;
6015 }
6016
6017 if (chunk_strcasecmp(entry, s) != 0)
6018 continue;
6019
6020 if (pos < 0)
6021 cur--;
6022 else
6023 cur++;
6024
6025 if (cur != pos)
6026 continue;
6027
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006028 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006029 return -1;
6030
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006031 memcpy(out->area, data_ptr, data_len);
6032 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006033 return 1;
6034 }
6035
6036 return 0;
6037
6038}
6039
6040/* Extract and format full DN from a X509_NAME and copy result into a chunk
6041 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6042 */
6043static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006044ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006045{
6046 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006047 ASN1_OBJECT *obj;
6048 ASN1_STRING *data;
6049 const unsigned char *data_ptr;
6050 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006051 int i, n, ln;
6052 int l = 0;
6053 const char *s;
6054 char *p;
6055 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006056 int name_count;
6057
6058
6059 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006060
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006061 out->data = 0;
6062 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006063 for (i = 0; i < name_count; i++) {
6064 ne = X509_NAME_get_entry(a, i);
6065 obj = X509_NAME_ENTRY_get_object(ne);
6066 data = X509_NAME_ENTRY_get_data(ne);
6067 data_ptr = ASN1_STRING_get0_data(data);
6068 data_len = ASN1_STRING_length(data);
6069 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006070 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006071 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006072 s = tmp;
6073 }
6074 ln = strlen(s);
6075
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006076 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006077 if (l > out->size)
6078 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006079 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006080
6081 *(p++)='/';
6082 memcpy(p, s, ln);
6083 p += ln;
6084 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006085 memcpy(p, data_ptr, data_len);
6086 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006087 }
6088
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006089 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006090 return 0;
6091
6092 return 1;
6093}
6094
Willy Tarreau119a4082016-12-22 21:58:38 +01006095/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6096 * to disable SNI.
6097 */
Willy Tarreau63076412015-07-10 11:33:32 +02006098void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6099{
6100#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006101 char *prev_name;
6102
Willy Tarreau63076412015-07-10 11:33:32 +02006103 if (!ssl_sock_is_ssl(conn))
6104 return;
6105
Willy Tarreau119a4082016-12-22 21:58:38 +01006106 /* if the SNI changes, we must destroy the reusable context so that a
6107 * new connection will present a new SNI. As an optimization we could
6108 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6109 * server.
6110 */
6111 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6112 if ((!prev_name && hostname) ||
6113 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6114 SSL_set_session(conn->xprt_ctx, NULL);
6115
Willy Tarreau63076412015-07-10 11:33:32 +02006116 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6117#endif
6118}
6119
Emeric Brun0abf8362014-06-24 18:26:41 +02006120/* Extract peer certificate's common name into the chunk dest
6121 * Returns
6122 * the len of the extracted common name
6123 * or 0 if no CN found in DN
6124 * or -1 on error case (i.e. no peer certificate)
6125 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006126int ssl_sock_get_remote_common_name(struct connection *conn,
6127 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006128{
6129 X509 *crt = NULL;
6130 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006131 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006132 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006133 .area = (char *)&find_cn,
6134 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006135 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006136 int result = -1;
David Safb76832014-05-08 23:42:08 -04006137
6138 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006139 goto out;
David Safb76832014-05-08 23:42:08 -04006140
6141 /* SSL_get_peer_certificate, it increase X509 * ref count */
6142 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6143 if (!crt)
6144 goto out;
6145
6146 name = X509_get_subject_name(crt);
6147 if (!name)
6148 goto out;
David Safb76832014-05-08 23:42:08 -04006149
Emeric Brun0abf8362014-06-24 18:26:41 +02006150 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6151out:
David Safb76832014-05-08 23:42:08 -04006152 if (crt)
6153 X509_free(crt);
6154
6155 return result;
6156}
6157
Dave McCowan328fb582014-07-30 10:39:13 -04006158/* returns 1 if client passed a certificate for this session, 0 if not */
6159int ssl_sock_get_cert_used_sess(struct connection *conn)
6160{
6161 X509 *crt = NULL;
6162
6163 if (!ssl_sock_is_ssl(conn))
6164 return 0;
6165
6166 /* SSL_get_peer_certificate, it increase X509 * ref count */
6167 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6168 if (!crt)
6169 return 0;
6170
6171 X509_free(crt);
6172 return 1;
6173}
6174
6175/* returns 1 if client passed a certificate for this connection, 0 if not */
6176int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006177{
6178 if (!ssl_sock_is_ssl(conn))
6179 return 0;
6180
6181 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6182}
6183
6184/* returns result from SSL verify */
6185unsigned int ssl_sock_get_verify_result(struct connection *conn)
6186{
6187 if (!ssl_sock_is_ssl(conn))
6188 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6189
6190 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6191}
6192
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006193/* Returns the application layer protocol name in <str> and <len> when known.
6194 * Zero is returned if the protocol name was not found, otherwise non-zero is
6195 * returned. The string is allocated in the SSL context and doesn't have to be
6196 * freed by the caller. NPN is also checked if available since older versions
6197 * of openssl (1.0.1) which are more common in field only support this one.
6198 */
6199static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6200{
6201 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6202 return 0;
6203
6204 *str = NULL;
6205
6206#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6207 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6208 if (*str)
6209 return 1;
6210#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006211#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006212 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6213 if (*str)
6214 return 1;
6215#endif
6216 return 0;
6217}
6218
Willy Tarreau7875d092012-09-10 08:20:03 +02006219/***** Below are some sample fetching functions for ACL/patterns *****/
6220
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006221static int
6222smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6223{
6224 struct connection *conn;
6225
6226 conn = objt_conn(smp->sess->origin);
6227 if (!conn || conn->xprt != &ssl_sock)
6228 return 0;
6229
6230 smp->flags = 0;
6231 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006232 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6233 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006234
6235 return 1;
6236}
6237
Emeric Brune64aef12012-09-21 13:15:06 +02006238/* boolean, returns true if client cert was present */
6239static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006240smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006241{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006242 struct connection *conn;
6243
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006244 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006245 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006246 return 0;
6247
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006248 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006249 smp->flags |= SMP_F_MAY_CHANGE;
6250 return 0;
6251 }
6252
6253 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006254 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006255 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006256
6257 return 1;
6258}
6259
Emeric Brun43e79582014-10-29 19:03:26 +01006260/* binary, returns a certificate in a binary chunk (der/raw).
6261 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6262 * should be use.
6263 */
6264static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006265smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006266{
6267 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6268 X509 *crt = NULL;
6269 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006270 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006271 struct connection *conn;
6272
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006273 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006274 if (!conn || conn->xprt != &ssl_sock)
6275 return 0;
6276
6277 if (!(conn->flags & CO_FL_CONNECTED)) {
6278 smp->flags |= SMP_F_MAY_CHANGE;
6279 return 0;
6280 }
6281
6282 if (cert_peer)
6283 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6284 else
6285 crt = SSL_get_certificate(conn->xprt_ctx);
6286
6287 if (!crt)
6288 goto out;
6289
6290 smp_trash = get_trash_chunk();
6291 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6292 goto out;
6293
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006294 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006295 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006296 ret = 1;
6297out:
6298 /* SSL_get_peer_certificate, it increase X509 * ref count */
6299 if (cert_peer && crt)
6300 X509_free(crt);
6301 return ret;
6302}
6303
Emeric Brunba841a12014-04-30 17:05:08 +02006304/* binary, returns serial of certificate in a binary chunk.
6305 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6306 * should be use.
6307 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006308static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006309smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006310{
Emeric Brunba841a12014-04-30 17:05:08 +02006311 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006312 X509 *crt = NULL;
6313 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006314 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006315 struct connection *conn;
6316
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006317 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006318 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006319 return 0;
6320
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006321 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006322 smp->flags |= SMP_F_MAY_CHANGE;
6323 return 0;
6324 }
6325
Emeric Brunba841a12014-04-30 17:05:08 +02006326 if (cert_peer)
6327 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6328 else
6329 crt = SSL_get_certificate(conn->xprt_ctx);
6330
Willy Tarreau8d598402012-10-22 17:58:39 +02006331 if (!crt)
6332 goto out;
6333
Willy Tarreau47ca5452012-12-23 20:22:19 +01006334 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006335 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6336 goto out;
6337
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006338 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006339 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006340 ret = 1;
6341out:
Emeric Brunba841a12014-04-30 17:05:08 +02006342 /* SSL_get_peer_certificate, it increase X509 * ref count */
6343 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006344 X509_free(crt);
6345 return ret;
6346}
Emeric Brune64aef12012-09-21 13:15:06 +02006347
Emeric Brunba841a12014-04-30 17:05:08 +02006348/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6349 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6350 * should be use.
6351 */
James Votha051b4a2013-05-14 20:37:59 +02006352static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006353smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006354{
Emeric Brunba841a12014-04-30 17:05:08 +02006355 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006356 X509 *crt = NULL;
6357 const EVP_MD *digest;
6358 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006359 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006360 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006361
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006362 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006363 if (!conn || conn->xprt != &ssl_sock)
6364 return 0;
6365
6366 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006367 smp->flags |= SMP_F_MAY_CHANGE;
6368 return 0;
6369 }
6370
Emeric Brunba841a12014-04-30 17:05:08 +02006371 if (cert_peer)
6372 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6373 else
6374 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006375 if (!crt)
6376 goto out;
6377
6378 smp_trash = get_trash_chunk();
6379 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006380 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6381 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006382
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006383 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006384 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006385 ret = 1;
6386out:
Emeric Brunba841a12014-04-30 17:05:08 +02006387 /* SSL_get_peer_certificate, it increase X509 * ref count */
6388 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006389 X509_free(crt);
6390 return ret;
6391}
6392
Emeric Brunba841a12014-04-30 17:05:08 +02006393/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6394 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6395 * should be use.
6396 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006397static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006398smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006399{
Emeric Brunba841a12014-04-30 17:05:08 +02006400 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006401 X509 *crt = NULL;
6402 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006403 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006404 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006405
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006406 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006407 if (!conn || conn->xprt != &ssl_sock)
6408 return 0;
6409
6410 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006411 smp->flags |= SMP_F_MAY_CHANGE;
6412 return 0;
6413 }
6414
Emeric Brunba841a12014-04-30 17:05:08 +02006415 if (cert_peer)
6416 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6417 else
6418 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006419 if (!crt)
6420 goto out;
6421
Willy Tarreau47ca5452012-12-23 20:22:19 +01006422 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006423 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6424 goto out;
6425
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006426 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006427 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006428 ret = 1;
6429out:
Emeric Brunba841a12014-04-30 17:05:08 +02006430 /* SSL_get_peer_certificate, it increase X509 * ref count */
6431 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006432 X509_free(crt);
6433 return ret;
6434}
6435
Emeric Brunba841a12014-04-30 17:05:08 +02006436/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6437 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6438 * should be use.
6439 */
Emeric Brun87855892012-10-17 17:39:35 +02006440static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006441smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006442{
Emeric Brunba841a12014-04-30 17:05:08 +02006443 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006444 X509 *crt = NULL;
6445 X509_NAME *name;
6446 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006447 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006448 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006449
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006450 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006451 if (!conn || conn->xprt != &ssl_sock)
6452 return 0;
6453
6454 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006455 smp->flags |= SMP_F_MAY_CHANGE;
6456 return 0;
6457 }
6458
Emeric Brunba841a12014-04-30 17:05:08 +02006459 if (cert_peer)
6460 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6461 else
6462 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006463 if (!crt)
6464 goto out;
6465
6466 name = X509_get_issuer_name(crt);
6467 if (!name)
6468 goto out;
6469
Willy Tarreau47ca5452012-12-23 20:22:19 +01006470 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006471 if (args && args[0].type == ARGT_STR) {
6472 int pos = 1;
6473
6474 if (args[1].type == ARGT_SINT)
6475 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006476
6477 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6478 goto out;
6479 }
6480 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6481 goto out;
6482
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006483 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006484 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006485 ret = 1;
6486out:
Emeric Brunba841a12014-04-30 17:05:08 +02006487 /* SSL_get_peer_certificate, it increase X509 * ref count */
6488 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006489 X509_free(crt);
6490 return ret;
6491}
6492
Emeric Brunba841a12014-04-30 17:05:08 +02006493/* string, returns notbefore date in ASN1_UTCTIME format.
6494 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6495 * should be use.
6496 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006497static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006498smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006499{
Emeric Brunba841a12014-04-30 17:05:08 +02006500 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006501 X509 *crt = NULL;
6502 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006503 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006504 struct connection *conn;
6505
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006506 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006507 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006508 return 0;
6509
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006510 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006511 smp->flags |= SMP_F_MAY_CHANGE;
6512 return 0;
6513 }
6514
Emeric Brunba841a12014-04-30 17:05:08 +02006515 if (cert_peer)
6516 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6517 else
6518 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006519 if (!crt)
6520 goto out;
6521
Willy Tarreau47ca5452012-12-23 20:22:19 +01006522 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006523 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6524 goto out;
6525
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006526 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006527 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006528 ret = 1;
6529out:
Emeric Brunba841a12014-04-30 17:05:08 +02006530 /* SSL_get_peer_certificate, it increase X509 * ref count */
6531 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006532 X509_free(crt);
6533 return ret;
6534}
6535
Emeric Brunba841a12014-04-30 17:05:08 +02006536/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6537 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6538 * should be use.
6539 */
Emeric Brun87855892012-10-17 17:39:35 +02006540static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006541smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006542{
Emeric Brunba841a12014-04-30 17:05:08 +02006543 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006544 X509 *crt = NULL;
6545 X509_NAME *name;
6546 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006547 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006548 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006549
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006550 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006551 if (!conn || conn->xprt != &ssl_sock)
6552 return 0;
6553
6554 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006555 smp->flags |= SMP_F_MAY_CHANGE;
6556 return 0;
6557 }
6558
Emeric Brunba841a12014-04-30 17:05:08 +02006559 if (cert_peer)
6560 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6561 else
6562 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006563 if (!crt)
6564 goto out;
6565
6566 name = X509_get_subject_name(crt);
6567 if (!name)
6568 goto out;
6569
Willy Tarreau47ca5452012-12-23 20:22:19 +01006570 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006571 if (args && args[0].type == ARGT_STR) {
6572 int pos = 1;
6573
6574 if (args[1].type == ARGT_SINT)
6575 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006576
6577 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6578 goto out;
6579 }
6580 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6581 goto out;
6582
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006583 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006584 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006585 ret = 1;
6586out:
Emeric Brunba841a12014-04-30 17:05:08 +02006587 /* SSL_get_peer_certificate, it increase X509 * ref count */
6588 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006589 X509_free(crt);
6590 return ret;
6591}
Emeric Brun9143d372012-12-20 15:44:16 +01006592
6593/* integer, returns true if current session use a client certificate */
6594static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006595smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006596{
6597 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006598 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006599
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006600 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006601 if (!conn || conn->xprt != &ssl_sock)
6602 return 0;
6603
6604 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006605 smp->flags |= SMP_F_MAY_CHANGE;
6606 return 0;
6607 }
6608
6609 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006610 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006611 if (crt) {
6612 X509_free(crt);
6613 }
6614
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006615 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006616 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006617 return 1;
6618}
6619
Emeric Brunba841a12014-04-30 17:05:08 +02006620/* integer, returns the certificate version
6621 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6622 * should be use.
6623 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006624static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006625smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006626{
Emeric Brunba841a12014-04-30 17:05:08 +02006627 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006628 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006629 struct connection *conn;
6630
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006631 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006632 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006633 return 0;
6634
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006635 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006636 smp->flags |= SMP_F_MAY_CHANGE;
6637 return 0;
6638 }
6639
Emeric Brunba841a12014-04-30 17:05:08 +02006640 if (cert_peer)
6641 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6642 else
6643 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006644 if (!crt)
6645 return 0;
6646
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006647 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006648 /* SSL_get_peer_certificate increase X509 * ref count */
6649 if (cert_peer)
6650 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006651 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006652
6653 return 1;
6654}
6655
Emeric Brunba841a12014-04-30 17:05:08 +02006656/* string, returns the certificate's signature algorithm.
6657 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6658 * should be use.
6659 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006660static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006661smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006662{
Emeric Brunba841a12014-04-30 17:05:08 +02006663 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006664 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006665 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006666 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006667 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006668
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006669 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006670 if (!conn || conn->xprt != &ssl_sock)
6671 return 0;
6672
6673 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006674 smp->flags |= SMP_F_MAY_CHANGE;
6675 return 0;
6676 }
6677
Emeric Brunba841a12014-04-30 17:05:08 +02006678 if (cert_peer)
6679 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6680 else
6681 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006682 if (!crt)
6683 return 0;
6684
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006685 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6686 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006687
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006688 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6689 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006690 /* SSL_get_peer_certificate increase X509 * ref count */
6691 if (cert_peer)
6692 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006693 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006694 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006695
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006696 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006697 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006698 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006699 /* SSL_get_peer_certificate increase X509 * ref count */
6700 if (cert_peer)
6701 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006702
6703 return 1;
6704}
6705
Emeric Brunba841a12014-04-30 17:05:08 +02006706/* string, returns the certificate's key algorithm.
6707 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6708 * should be use.
6709 */
Emeric Brun521a0112012-10-22 12:22:55 +02006710static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006711smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006712{
Emeric Brunba841a12014-04-30 17:05:08 +02006713 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006714 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006715 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006716 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006717 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006718
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006719 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006720 if (!conn || conn->xprt != &ssl_sock)
6721 return 0;
6722
6723 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006724 smp->flags |= SMP_F_MAY_CHANGE;
6725 return 0;
6726 }
6727
Emeric Brunba841a12014-04-30 17:05:08 +02006728 if (cert_peer)
6729 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6730 else
6731 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006732 if (!crt)
6733 return 0;
6734
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006735 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6736 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006737
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006738 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6739 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006740 /* SSL_get_peer_certificate increase X509 * ref count */
6741 if (cert_peer)
6742 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006743 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006744 }
Emeric Brun521a0112012-10-22 12:22:55 +02006745
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006746 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006747 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006748 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006749 if (cert_peer)
6750 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006751
6752 return 1;
6753}
6754
Emeric Brun645ae792014-04-30 14:21:06 +02006755/* boolean, returns true if front conn. transport layer is SSL.
6756 * This function is also usable on backend conn if the fetch keyword 5th
6757 * char is 'b'.
6758 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006759static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006760smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006761{
Emeric Bruneb8def92018-02-19 15:59:48 +01006762 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6763 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006764
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006765 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006766 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006767 return 1;
6768}
6769
Emeric Brun2525b6b2012-10-18 15:59:43 +02006770/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006771static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006772smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006773{
6774#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006775 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006776
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006777 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006778 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006779 conn->xprt_ctx &&
6780 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006781 return 1;
6782#else
6783 return 0;
6784#endif
6785}
6786
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006787/* boolean, returns true if client session has been resumed.
6788 * This function is also usable on backend conn if the fetch keyword 5th
6789 * char is 'b'.
6790 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006791static int
6792smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6793{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006794 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6795 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6796
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006797
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006798 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006799 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006800 conn->xprt_ctx &&
6801 SSL_session_reused(conn->xprt_ctx);
6802 return 1;
6803}
6804
Emeric Brun645ae792014-04-30 14:21:06 +02006805/* string, returns the used cipher if front conn. transport layer is SSL.
6806 * This function is also usable on backend conn if the fetch keyword 5th
6807 * char is 'b'.
6808 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006809static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006810smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006811{
Emeric Bruneb8def92018-02-19 15:59:48 +01006812 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6813 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006814
Willy Tarreaube508f12016-03-10 11:47:01 +01006815 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006816 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006817 return 0;
6818
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006819 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6820 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006821 return 0;
6822
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006823 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006824 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006825 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006826
6827 return 1;
6828}
6829
Emeric Brun645ae792014-04-30 14:21:06 +02006830/* integer, returns the algoritm's keysize if front conn. transport layer
6831 * is SSL.
6832 * This function is also usable on backend conn if the fetch keyword 5th
6833 * char is 'b'.
6834 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006835static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006836smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006837{
Emeric Bruneb8def92018-02-19 15:59:48 +01006838 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6839 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006840 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006841
Emeric Brun589fcad2012-10-16 14:13:26 +02006842 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006843 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006844 return 0;
6845
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006846 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006847 return 0;
6848
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006849 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006850 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006851
6852 return 1;
6853}
6854
Emeric Brun645ae792014-04-30 14:21:06 +02006855/* integer, returns the used keysize if front conn. transport layer is SSL.
6856 * This function is also usable on backend conn if the fetch keyword 5th
6857 * char is 'b'.
6858 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006859static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006860smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006861{
Emeric Bruneb8def92018-02-19 15:59:48 +01006862 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6863 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006864
Emeric Brun589fcad2012-10-16 14:13:26 +02006865 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006866 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6867 return 0;
6868
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006869 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6870 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006871 return 0;
6872
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006873 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006874
6875 return 1;
6876}
6877
Bernard Spil13c53f82018-02-15 13:34:58 +01006878#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006879static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006880smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006881{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006882 struct connection *conn;
6883
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006884 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006885 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006886
Olivier Houchard6b77f492018-11-22 18:18:29 +01006887 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6888 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006889 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6890 return 0;
6891
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006892 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006893 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006894 (const unsigned char **)&smp->data.u.str.area,
6895 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006896
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006897 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006898 return 0;
6899
6900 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006901}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006902#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006903
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006904#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006905static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006906smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006907{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006908 struct connection *conn;
6909
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006910 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006911 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006912
Olivier Houchard6b77f492018-11-22 18:18:29 +01006913 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6914 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6915
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006916 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006917 return 0;
6918
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006919 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006920 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006921 (const unsigned char **)&smp->data.u.str.area,
6922 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006923
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006924 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006925 return 0;
6926
6927 return 1;
6928}
6929#endif
6930
Emeric Brun645ae792014-04-30 14:21:06 +02006931/* string, returns the used protocol if front conn. transport layer is SSL.
6932 * This function is also usable on backend conn if the fetch keyword 5th
6933 * char is 'b'.
6934 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006935static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006936smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006937{
Emeric Bruneb8def92018-02-19 15:59:48 +01006938 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6939 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006940
Emeric Brun589fcad2012-10-16 14:13:26 +02006941 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006942 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6943 return 0;
6944
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006945 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6946 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006947 return 0;
6948
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006949 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006950 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006951 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006952
6953 return 1;
6954}
6955
Willy Tarreau87b09662015-04-03 00:22:06 +02006956/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006957 * This function is also usable on backend conn if the fetch keyword 5th
6958 * char is 'b'.
6959 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006960#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006961static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006962smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006963{
Emeric Bruneb8def92018-02-19 15:59:48 +01006964 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6965 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006966 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006967
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006968 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006969 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006970
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006971 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6972 return 0;
6973
Willy Tarreau192252e2015-04-04 01:47:55 +02006974 ssl_sess = SSL_get_session(conn->xprt_ctx);
6975 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006976 return 0;
6977
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006978 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6979 (unsigned int *)&smp->data.u.str.data);
6980 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006981 return 0;
6982
6983 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006984}
Patrick Hemmer41966772018-04-28 19:15:48 -04006985#endif
6986
Emeric Brunfe68f682012-10-16 14:59:28 +02006987
Patrick Hemmere0275472018-04-28 19:15:51 -04006988#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6989static int
6990smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6991{
6992 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6993 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6994 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006995 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006996
6997 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6998 return 0;
6999
7000 ssl_sess = SSL_get_session(conn->xprt_ctx);
7001 if (!ssl_sess)
7002 return 0;
7003
7004 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007005 data->data = SSL_SESSION_get_master_key(ssl_sess,
7006 (unsigned char *) data->area,
7007 data->size);
7008 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007009 return 0;
7010
7011 smp->flags = 0;
7012 smp->data.type = SMP_T_BIN;
7013 smp->data.u.str = *data;
7014
7015 return 1;
7016}
7017#endif
7018
Patrick Hemmer41966772018-04-28 19:15:48 -04007019#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007020static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007021smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007022{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007023 struct connection *conn;
7024
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007025 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007026 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007027
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007028 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007029 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7030 return 0;
7031
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007032 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7033 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007034 return 0;
7035
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007036 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007037 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007038}
Patrick Hemmer41966772018-04-28 19:15:48 -04007039#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007040
David Sc1ad52e2014-04-08 18:48:47 -04007041static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007042smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7043{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007044 struct connection *conn;
7045 struct ssl_capture *capture;
7046
7047 conn = objt_conn(smp->sess->origin);
7048 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7049 return 0;
7050
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007051 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007052 if (!capture)
7053 return 0;
7054
7055 smp->flags = SMP_F_CONST;
7056 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007057 smp->data.u.str.area = capture->ciphersuite;
7058 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007059 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007060}
7061
7062static int
7063smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7064{
Willy Tarreau83061a82018-07-13 11:56:34 +02007065 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007066
7067 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7068 return 0;
7069
7070 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007071 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007072 smp->data.type = SMP_T_BIN;
7073 smp->data.u.str = *data;
7074 return 1;
7075}
7076
7077static int
7078smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7079{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007080 struct connection *conn;
7081 struct ssl_capture *capture;
7082
7083 conn = objt_conn(smp->sess->origin);
7084 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7085 return 0;
7086
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007087 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007088 if (!capture)
7089 return 0;
7090
7091 smp->data.type = SMP_T_SINT;
7092 smp->data.u.sint = capture->xxh64;
7093 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007094}
7095
7096static int
7097smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7098{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007099#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007100 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007101 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007102
7103 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7104 return 0;
7105
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007106 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007107 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007108 const char *str;
7109 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007110 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007111 uint16_t id = (bin[0] << 8) | bin[1];
7112#if defined(OPENSSL_IS_BORINGSSL)
7113 cipher = SSL_get_cipher_by_value(id);
7114#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007115 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007116 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7117#endif
7118 str = SSL_CIPHER_get_name(cipher);
7119 if (!str || strcmp(str, "(NONE)") == 0)
7120 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007121 else
7122 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7123 }
7124 smp->data.type = SMP_T_STR;
7125 smp->data.u.str = *data;
7126 return 1;
7127#else
7128 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7129#endif
7130}
7131
Patrick Hemmer41966772018-04-28 19:15:48 -04007132#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007133static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007134smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007135{
Emeric Bruneb8def92018-02-19 15:59:48 +01007136 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7137 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007138 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007139 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007140
7141 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007142 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7143 return 0;
7144
7145 if (!(conn->flags & CO_FL_CONNECTED)) {
7146 smp->flags |= SMP_F_MAY_CHANGE;
7147 return 0;
7148 }
7149
7150 finished_trash = get_trash_chunk();
7151 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007152 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7153 finished_trash->area,
7154 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007155 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007156 finished_len = SSL_get_finished(conn->xprt_ctx,
7157 finished_trash->area,
7158 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007159
7160 if (!finished_len)
7161 return 0;
7162
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007163 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007164 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007165 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007166
7167 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007168}
Patrick Hemmer41966772018-04-28 19:15:48 -04007169#endif
David Sc1ad52e2014-04-08 18:48:47 -04007170
Emeric Brun2525b6b2012-10-18 15:59:43 +02007171/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007172static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007173smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007174{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007175 struct connection *conn;
7176
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007177 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007178 if (!conn || conn->xprt != &ssl_sock)
7179 return 0;
7180
7181 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007182 smp->flags = SMP_F_MAY_CHANGE;
7183 return 0;
7184 }
7185
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007186 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007187 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007188 smp->flags = 0;
7189
7190 return 1;
7191}
7192
Emeric Brun2525b6b2012-10-18 15:59:43 +02007193/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007194static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007195smp_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 +02007196{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007197 struct connection *conn;
7198
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007199 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007200 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007201 return 0;
7202
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007203 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007204 smp->flags = SMP_F_MAY_CHANGE;
7205 return 0;
7206 }
7207
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007208 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007209 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007210 smp->flags = 0;
7211
7212 return 1;
7213}
7214
Emeric Brun2525b6b2012-10-18 15:59:43 +02007215/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007216static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007217smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007218{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007219 struct connection *conn;
7220
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007221 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007222 if (!conn || conn->xprt != &ssl_sock)
7223 return 0;
7224
7225 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007226 smp->flags = SMP_F_MAY_CHANGE;
7227 return 0;
7228 }
7229
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007230 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007231 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007232 smp->flags = 0;
7233
7234 return 1;
7235}
7236
Emeric Brun2525b6b2012-10-18 15:59:43 +02007237/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007238static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007239smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007240{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007241 struct connection *conn;
7242
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007243 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007244 if (!conn || conn->xprt != &ssl_sock)
7245 return 0;
7246
7247 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007248 smp->flags = SMP_F_MAY_CHANGE;
7249 return 0;
7250 }
7251
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007252 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007253 return 0;
7254
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007255 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007256 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007257 smp->flags = 0;
7258
7259 return 1;
7260}
7261
Emeric Brunfb510ea2012-10-05 12:00:26 +02007262/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007263static 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 +02007264{
7265 if (!*args[cur_arg + 1]) {
7266 if (err)
7267 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7268 return ERR_ALERT | ERR_FATAL;
7269 }
7270
Willy Tarreauef934602016-12-22 23:12:01 +01007271 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7272 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007273 else
7274 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007275
Emeric Brund94b3fe2012-09-20 18:23:56 +02007276 return 0;
7277}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007278static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7279{
7280 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7281}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007282
Christopher Faulet31af49d2015-06-09 17:29:50 +02007283/* parse the "ca-sign-file" bind keyword */
7284static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7285{
7286 if (!*args[cur_arg + 1]) {
7287 if (err)
7288 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7289 return ERR_ALERT | ERR_FATAL;
7290 }
7291
Willy Tarreauef934602016-12-22 23:12:01 +01007292 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7293 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007294 else
7295 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7296
7297 return 0;
7298}
7299
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007300/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007301static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7302{
7303 if (!*args[cur_arg + 1]) {
7304 if (err)
7305 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7306 return ERR_ALERT | ERR_FATAL;
7307 }
7308 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7309 return 0;
7310}
7311
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007312/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007313static 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 +02007314{
7315 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007316 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007317 return ERR_ALERT | ERR_FATAL;
7318 }
7319
Emeric Brun76d88952012-10-05 15:47:31 +02007320 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007321 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007322 return 0;
7323}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007324static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7325{
7326 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7327}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007328
7329#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7330/* parse the "ciphersuites" bind keyword */
7331static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7332{
7333 if (!*args[cur_arg + 1]) {
7334 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7335 return ERR_ALERT | ERR_FATAL;
7336 }
7337
7338 free(conf->ciphersuites);
7339 conf->ciphersuites = strdup(args[cur_arg + 1]);
7340 return 0;
7341}
7342static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7343{
7344 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7345}
7346#endif
7347
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007348/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007349static 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 +02007350{
Willy Tarreau38011032013-08-13 16:59:39 +02007351 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007352
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007353 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007354 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007355 return ERR_ALERT | ERR_FATAL;
7356 }
7357
Willy Tarreauef934602016-12-22 23:12:01 +01007358 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7359 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007360 memprintf(err, "'%s' : path too long", args[cur_arg]);
7361 return ERR_ALERT | ERR_FATAL;
7362 }
Willy Tarreauef934602016-12-22 23:12:01 +01007363 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007364 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007365 return ERR_ALERT | ERR_FATAL;
7366
7367 return 0;
7368 }
7369
Willy Tarreau03209342016-12-22 17:08:28 +01007370 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007371 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007372
7373 return 0;
7374}
7375
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007376/* parse the "crt-list" bind keyword */
7377static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7378{
7379 if (!*args[cur_arg + 1]) {
7380 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7381 return ERR_ALERT | ERR_FATAL;
7382 }
7383
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007384 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007385 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007386 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007387 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007388
7389 return 0;
7390}
7391
Emeric Brunfb510ea2012-10-05 12:00:26 +02007392/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007393static 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 +02007394{
Emeric Brun051cdab2012-10-02 19:25:50 +02007395#ifndef X509_V_FLAG_CRL_CHECK
7396 if (err)
7397 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7398 return ERR_ALERT | ERR_FATAL;
7399#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007400 if (!*args[cur_arg + 1]) {
7401 if (err)
7402 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7403 return ERR_ALERT | ERR_FATAL;
7404 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007405
Willy Tarreauef934602016-12-22 23:12:01 +01007406 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7407 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007408 else
7409 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007410
Emeric Brun2b58d042012-09-20 17:10:03 +02007411 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007412#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007413}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007414static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7415{
7416 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7417}
Emeric Brun2b58d042012-09-20 17:10:03 +02007418
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007419/* parse the "curves" bind keyword keyword */
7420static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7421{
7422#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7423 if (!*args[cur_arg + 1]) {
7424 if (err)
7425 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7426 return ERR_ALERT | ERR_FATAL;
7427 }
7428 conf->curves = strdup(args[cur_arg + 1]);
7429 return 0;
7430#else
7431 if (err)
7432 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7433 return ERR_ALERT | ERR_FATAL;
7434#endif
7435}
7436static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7437{
7438 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7439}
7440
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007441/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007442static 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 +02007443{
7444#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7445 if (err)
7446 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7447 return ERR_ALERT | ERR_FATAL;
7448#elif defined(OPENSSL_NO_ECDH)
7449 if (err)
7450 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7451 return ERR_ALERT | ERR_FATAL;
7452#else
7453 if (!*args[cur_arg + 1]) {
7454 if (err)
7455 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7456 return ERR_ALERT | ERR_FATAL;
7457 }
7458
7459 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007460
7461 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007462#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007463}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007464static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7465{
7466 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7467}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007468
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007469/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007470static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7471{
7472 int code;
7473 char *p = args[cur_arg + 1];
7474 unsigned long long *ignerr = &conf->crt_ignerr;
7475
7476 if (!*p) {
7477 if (err)
7478 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7479 return ERR_ALERT | ERR_FATAL;
7480 }
7481
7482 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7483 ignerr = &conf->ca_ignerr;
7484
7485 if (strcmp(p, "all") == 0) {
7486 *ignerr = ~0ULL;
7487 return 0;
7488 }
7489
7490 while (p) {
7491 code = atoi(p);
7492 if ((code <= 0) || (code > 63)) {
7493 if (err)
7494 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7495 args[cur_arg], code, args[cur_arg + 1]);
7496 return ERR_ALERT | ERR_FATAL;
7497 }
7498 *ignerr |= 1ULL << code;
7499 p = strchr(p, ',');
7500 if (p)
7501 p++;
7502 }
7503
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007504 return 0;
7505}
7506
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007507/* parse tls_method_options "no-xxx" and "force-xxx" */
7508static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007509{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007510 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007511 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007512 p = strchr(arg, '-');
7513 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007514 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007515 p++;
7516 if (!strcmp(p, "sslv3"))
7517 v = CONF_SSLV3;
7518 else if (!strcmp(p, "tlsv10"))
7519 v = CONF_TLSV10;
7520 else if (!strcmp(p, "tlsv11"))
7521 v = CONF_TLSV11;
7522 else if (!strcmp(p, "tlsv12"))
7523 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007524 else if (!strcmp(p, "tlsv13"))
7525 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007526 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007527 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007528 if (!strncmp(arg, "no-", 3))
7529 methods->flags |= methodVersions[v].flag;
7530 else if (!strncmp(arg, "force-", 6))
7531 methods->min = methods->max = v;
7532 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007533 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007534 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007535 fail:
7536 if (err)
7537 memprintf(err, "'%s' : option not implemented", arg);
7538 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007539}
7540
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007541static 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 +02007542{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007543 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007544}
7545
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007546static 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 +02007547{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007548 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7549}
7550
7551/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7552static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7553{
7554 uint16_t i, v = 0;
7555 char *argv = args[cur_arg + 1];
7556 if (!*argv) {
7557 if (err)
7558 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7559 return ERR_ALERT | ERR_FATAL;
7560 }
7561 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7562 if (!strcmp(argv, methodVersions[i].name))
7563 v = i;
7564 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007565 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007566 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007567 return ERR_ALERT | ERR_FATAL;
7568 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007569 if (!strcmp("ssl-min-ver", args[cur_arg]))
7570 methods->min = v;
7571 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7572 methods->max = v;
7573 else {
7574 if (err)
7575 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7576 return ERR_ALERT | ERR_FATAL;
7577 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007578 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007579}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007580
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007581static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7582{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007583#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007584 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 +02007585#endif
7586 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7587}
7588
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007589static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7590{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007591 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007592}
7593
7594static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7595{
7596 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7597}
7598
Emeric Brun2d0c4822012-10-02 13:45:20 +02007599/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007600static 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 +02007601{
Emeric Brun89675492012-10-05 13:48:26 +02007602 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007603 return 0;
7604}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007605
Olivier Houchardc2aae742017-09-22 18:26:28 +02007606/* parse the "allow-0rtt" bind keyword */
7607static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7608{
7609 conf->early_data = 1;
7610 return 0;
7611}
7612
7613static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7614{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007615 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007616 return 0;
7617}
7618
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007619/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007620static 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 +02007621{
Bernard Spil13c53f82018-02-15 13:34:58 +01007622#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007623 char *p1, *p2;
7624
7625 if (!*args[cur_arg + 1]) {
7626 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7627 return ERR_ALERT | ERR_FATAL;
7628 }
7629
7630 free(conf->npn_str);
7631
Willy Tarreau3724da12016-02-12 17:11:12 +01007632 /* the NPN string is built as a suite of (<len> <name>)*,
7633 * so we reuse each comma to store the next <len> and need
7634 * one more for the end of the string.
7635 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007636 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007637 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007638 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7639
7640 /* replace commas with the name length */
7641 p1 = conf->npn_str;
7642 p2 = p1 + 1;
7643 while (1) {
7644 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7645 if (!p2)
7646 p2 = p1 + 1 + strlen(p1 + 1);
7647
7648 if (p2 - (p1 + 1) > 255) {
7649 *p2 = '\0';
7650 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7651 return ERR_ALERT | ERR_FATAL;
7652 }
7653
7654 *p1 = p2 - (p1 + 1);
7655 p1 = p2;
7656
7657 if (!*p2)
7658 break;
7659
7660 *(p2++) = '\0';
7661 }
7662 return 0;
7663#else
7664 if (err)
7665 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7666 return ERR_ALERT | ERR_FATAL;
7667#endif
7668}
7669
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007670static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7671{
7672 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7673}
7674
Willy Tarreauab861d32013-04-02 02:30:41 +02007675/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007676static 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 +02007677{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007678#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007679 char *p1, *p2;
7680
7681 if (!*args[cur_arg + 1]) {
7682 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7683 return ERR_ALERT | ERR_FATAL;
7684 }
7685
7686 free(conf->alpn_str);
7687
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007688 /* the ALPN string is built as a suite of (<len> <name>)*,
7689 * so we reuse each comma to store the next <len> and need
7690 * one more for the end of the string.
7691 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007692 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007693 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007694 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7695
7696 /* replace commas with the name length */
7697 p1 = conf->alpn_str;
7698 p2 = p1 + 1;
7699 while (1) {
7700 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7701 if (!p2)
7702 p2 = p1 + 1 + strlen(p1 + 1);
7703
7704 if (p2 - (p1 + 1) > 255) {
7705 *p2 = '\0';
7706 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7707 return ERR_ALERT | ERR_FATAL;
7708 }
7709
7710 *p1 = p2 - (p1 + 1);
7711 p1 = p2;
7712
7713 if (!*p2)
7714 break;
7715
7716 *(p2++) = '\0';
7717 }
7718 return 0;
7719#else
7720 if (err)
7721 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7722 return ERR_ALERT | ERR_FATAL;
7723#endif
7724}
7725
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007726static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7727{
7728 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7729}
7730
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007731/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007732static 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 +02007733{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007734 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007735 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007736
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007737 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7738 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007739#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7740 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7741 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7742#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007743 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007744 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7745 if (!conf->ssl_conf.ssl_methods.min)
7746 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7747 if (!conf->ssl_conf.ssl_methods.max)
7748 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007749
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007750 return 0;
7751}
7752
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007753/* parse the "prefer-client-ciphers" bind keyword */
7754static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7755{
7756 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7757 return 0;
7758}
7759
Christopher Faulet31af49d2015-06-09 17:29:50 +02007760/* parse the "generate-certificates" bind keyword */
7761static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7762{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007763#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007764 conf->generate_certs = 1;
7765#else
7766 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7767 err && *err ? *err : "");
7768#endif
7769 return 0;
7770}
7771
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007772/* parse the "strict-sni" bind keyword */
7773static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7774{
7775 conf->strict_sni = 1;
7776 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007777}
7778
7779/* parse the "tls-ticket-keys" bind keyword */
7780static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7781{
7782#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7783 FILE *f;
7784 int i = 0;
7785 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007786 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007787
7788 if (!*args[cur_arg + 1]) {
7789 if (err)
7790 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7791 return ERR_ALERT | ERR_FATAL;
7792 }
7793
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007794 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007795 if (keys_ref) {
7796 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007797 conf->keys_ref = keys_ref;
7798 return 0;
7799 }
7800
Vincent Bernat02779b62016-04-03 13:48:43 +02007801 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007802 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007803
7804 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7805 if (err)
7806 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7807 return ERR_ALERT | ERR_FATAL;
7808 }
7809
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007810 keys_ref->filename = strdup(args[cur_arg + 1]);
7811
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007812 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7813 int len = strlen(thisline);
7814 /* Strip newline characters from the end */
7815 if(thisline[len - 1] == '\n')
7816 thisline[--len] = 0;
7817
7818 if(thisline[len - 1] == '\r')
7819 thisline[--len] = 0;
7820
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007821 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 +01007822 if (err)
7823 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007824 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007825 return ERR_ALERT | ERR_FATAL;
7826 }
7827 i++;
7828 }
7829
7830 if (i < TLS_TICKETS_NO) {
7831 if (err)
7832 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 +02007833 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007834 return ERR_ALERT | ERR_FATAL;
7835 }
7836
7837 fclose(f);
7838
7839 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007840 i -= 2;
7841 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007842 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007843 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007844 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007845 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007846
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007847 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7848
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007849 return 0;
7850#else
7851 if (err)
7852 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7853 return ERR_ALERT | ERR_FATAL;
7854#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007855}
7856
Emeric Brund94b3fe2012-09-20 18:23:56 +02007857/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007858static 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 +02007859{
7860 if (!*args[cur_arg + 1]) {
7861 if (err)
7862 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7863 return ERR_ALERT | ERR_FATAL;
7864 }
7865
7866 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007867 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007868 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007869 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007870 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007871 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007872 else {
7873 if (err)
7874 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7875 args[cur_arg], args[cur_arg + 1]);
7876 return ERR_ALERT | ERR_FATAL;
7877 }
7878
7879 return 0;
7880}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007881static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7882{
7883 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7884}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007885
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007886/* parse the "no-ca-names" bind keyword */
7887static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7888{
7889 conf->no_ca_names = 1;
7890 return 0;
7891}
7892static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7893{
7894 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7895}
7896
Willy Tarreau92faadf2012-10-10 23:04:25 +02007897/************** "server" keywords ****************/
7898
Olivier Houchardc7566002018-11-20 23:33:50 +01007899/* parse the "npn" bind keyword */
7900static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7901{
7902#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7903 char *p1, *p2;
7904
7905 if (!*args[*cur_arg + 1]) {
7906 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7907 return ERR_ALERT | ERR_FATAL;
7908 }
7909
7910 free(newsrv->ssl_ctx.npn_str);
7911
7912 /* the NPN string is built as a suite of (<len> <name>)*,
7913 * so we reuse each comma to store the next <len> and need
7914 * one more for the end of the string.
7915 */
7916 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7917 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7918 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7919 newsrv->ssl_ctx.npn_len);
7920
7921 /* replace commas with the name length */
7922 p1 = newsrv->ssl_ctx.npn_str;
7923 p2 = p1 + 1;
7924 while (1) {
7925 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7926 newsrv->ssl_ctx.npn_len - (p1 + 1));
7927 if (!p2)
7928 p2 = p1 + 1 + strlen(p1 + 1);
7929
7930 if (p2 - (p1 + 1) > 255) {
7931 *p2 = '\0';
7932 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7933 return ERR_ALERT | ERR_FATAL;
7934 }
7935
7936 *p1 = p2 - (p1 + 1);
7937 p1 = p2;
7938
7939 if (!*p2)
7940 break;
7941
7942 *(p2++) = '\0';
7943 }
7944 return 0;
7945#else
7946 if (err)
7947 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7948 return ERR_ALERT | ERR_FATAL;
7949#endif
7950}
7951
7952/* parse the "alpn" bind keyword */
7953static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7954{
7955#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7956 char *p1, *p2;
7957
7958 if (!*args[*cur_arg + 1]) {
7959 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7960 return ERR_ALERT | ERR_FATAL;
7961 }
7962
7963 free(newsrv->ssl_ctx.alpn_str);
7964
7965 /* the ALPN string is built as a suite of (<len> <name>)*,
7966 * so we reuse each comma to store the next <len> and need
7967 * one more for the end of the string.
7968 */
7969 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7970 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7971 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7972 newsrv->ssl_ctx.alpn_len);
7973
7974 /* replace commas with the name length */
7975 p1 = newsrv->ssl_ctx.alpn_str;
7976 p2 = p1 + 1;
7977 while (1) {
7978 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7979 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7980 if (!p2)
7981 p2 = p1 + 1 + strlen(p1 + 1);
7982
7983 if (p2 - (p1 + 1) > 255) {
7984 *p2 = '\0';
7985 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7986 return ERR_ALERT | ERR_FATAL;
7987 }
7988
7989 *p1 = p2 - (p1 + 1);
7990 p1 = p2;
7991
7992 if (!*p2)
7993 break;
7994
7995 *(p2++) = '\0';
7996 }
7997 return 0;
7998#else
7999 if (err)
8000 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8001 return ERR_ALERT | ERR_FATAL;
8002#endif
8003}
8004
Emeric Brunef42d922012-10-11 16:11:36 +02008005/* parse the "ca-file" server keyword */
8006static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8007{
8008 if (!*args[*cur_arg + 1]) {
8009 if (err)
8010 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8011 return ERR_ALERT | ERR_FATAL;
8012 }
8013
Willy Tarreauef934602016-12-22 23:12:01 +01008014 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8015 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008016 else
8017 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8018
8019 return 0;
8020}
8021
Olivier Houchard9130a962017-10-17 17:33:43 +02008022/* parse the "check-sni" server keyword */
8023static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8024{
8025 if (!*args[*cur_arg + 1]) {
8026 if (err)
8027 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8028 return ERR_ALERT | ERR_FATAL;
8029 }
8030
8031 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8032 if (!newsrv->check.sni) {
8033 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8034 return ERR_ALERT | ERR_FATAL;
8035 }
8036 return 0;
8037
8038}
8039
Willy Tarreau92faadf2012-10-10 23:04:25 +02008040/* parse the "check-ssl" server keyword */
8041static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8042{
8043 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008044 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8045 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008046#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8047 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8048 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8049#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008050 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008051 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8052 if (!newsrv->ssl_ctx.methods.min)
8053 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8054 if (!newsrv->ssl_ctx.methods.max)
8055 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8056
Willy Tarreau92faadf2012-10-10 23:04:25 +02008057 return 0;
8058}
8059
8060/* parse the "ciphers" server keyword */
8061static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8062{
8063 if (!*args[*cur_arg + 1]) {
8064 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8065 return ERR_ALERT | ERR_FATAL;
8066 }
8067
8068 free(newsrv->ssl_ctx.ciphers);
8069 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8070 return 0;
8071}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008072
8073#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8074/* parse the "ciphersuites" server keyword */
8075static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8076{
8077 if (!*args[*cur_arg + 1]) {
8078 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8079 return ERR_ALERT | ERR_FATAL;
8080 }
8081
8082 free(newsrv->ssl_ctx.ciphersuites);
8083 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8084 return 0;
8085}
8086#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008087
Emeric Brunef42d922012-10-11 16:11:36 +02008088/* parse the "crl-file" server keyword */
8089static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8090{
8091#ifndef X509_V_FLAG_CRL_CHECK
8092 if (err)
8093 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8094 return ERR_ALERT | ERR_FATAL;
8095#else
8096 if (!*args[*cur_arg + 1]) {
8097 if (err)
8098 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8099 return ERR_ALERT | ERR_FATAL;
8100 }
8101
Willy Tarreauef934602016-12-22 23:12:01 +01008102 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8103 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008104 else
8105 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8106
8107 return 0;
8108#endif
8109}
8110
Emeric Bruna7aa3092012-10-26 12:58:00 +02008111/* parse the "crt" server keyword */
8112static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8113{
8114 if (!*args[*cur_arg + 1]) {
8115 if (err)
8116 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8117 return ERR_ALERT | ERR_FATAL;
8118 }
8119
Willy Tarreauef934602016-12-22 23:12:01 +01008120 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008121 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008122 else
8123 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8124
8125 return 0;
8126}
Emeric Brunef42d922012-10-11 16:11:36 +02008127
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008128/* parse the "no-check-ssl" server keyword */
8129static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8130{
8131 newsrv->check.use_ssl = 0;
8132 free(newsrv->ssl_ctx.ciphers);
8133 newsrv->ssl_ctx.ciphers = NULL;
8134 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8135 return 0;
8136}
8137
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008138/* parse the "no-send-proxy-v2-ssl" server keyword */
8139static int srv_parse_no_send_proxy_ssl(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 return 0;
8144}
8145
8146/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8147static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8148{
8149 newsrv->pp_opts &= ~SRV_PP_V2;
8150 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8151 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8152 return 0;
8153}
8154
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008155/* parse the "no-ssl" server keyword */
8156static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8157{
8158 newsrv->use_ssl = 0;
8159 free(newsrv->ssl_ctx.ciphers);
8160 newsrv->ssl_ctx.ciphers = NULL;
8161 return 0;
8162}
8163
Olivier Houchard522eea72017-11-03 16:27:47 +01008164/* parse the "allow-0rtt" server keyword */
8165static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8166{
8167 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8168 return 0;
8169}
8170
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008171/* parse the "no-ssl-reuse" server keyword */
8172static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8173{
8174 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8175 return 0;
8176}
8177
Emeric Brunf9c5c472012-10-11 15:28:34 +02008178/* parse the "no-tls-tickets" server keyword */
8179static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8180{
8181 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8182 return 0;
8183}
David Safb76832014-05-08 23:42:08 -04008184/* parse the "send-proxy-v2-ssl" server keyword */
8185static int srv_parse_send_proxy_ssl(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 return 0;
8190}
8191
8192/* parse the "send-proxy-v2-ssl-cn" server keyword */
8193static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8194{
8195 newsrv->pp_opts |= SRV_PP_V2;
8196 newsrv->pp_opts |= SRV_PP_V2_SSL;
8197 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8198 return 0;
8199}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008200
Willy Tarreau732eac42015-07-09 11:40:25 +02008201/* parse the "sni" server keyword */
8202static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8203{
8204#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8205 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8206 return ERR_ALERT | ERR_FATAL;
8207#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008208 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008209
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008210 arg = args[*cur_arg + 1];
8211 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008212 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8213 return ERR_ALERT | ERR_FATAL;
8214 }
8215
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008216 free(newsrv->sni_expr);
8217 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008218
Willy Tarreau732eac42015-07-09 11:40:25 +02008219 return 0;
8220#endif
8221}
8222
Willy Tarreau92faadf2012-10-10 23:04:25 +02008223/* parse the "ssl" server keyword */
8224static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8225{
8226 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008227 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8228 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008229#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8230 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8231 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8232#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008233 return 0;
8234}
8235
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008236/* parse the "ssl-reuse" server keyword */
8237static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8238{
8239 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8240 return 0;
8241}
8242
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008243/* parse the "tls-tickets" server keyword */
8244static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8245{
8246 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8247 return 0;
8248}
8249
Emeric Brunef42d922012-10-11 16:11:36 +02008250/* parse the "verify" server keyword */
8251static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8252{
8253 if (!*args[*cur_arg + 1]) {
8254 if (err)
8255 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8256 return ERR_ALERT | ERR_FATAL;
8257 }
8258
8259 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008260 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008261 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008262 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008263 else {
8264 if (err)
8265 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8266 args[*cur_arg], args[*cur_arg + 1]);
8267 return ERR_ALERT | ERR_FATAL;
8268 }
8269
Evan Broderbe554312013-06-27 00:05:25 -07008270 return 0;
8271}
8272
8273/* parse the "verifyhost" server keyword */
8274static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8275{
8276 if (!*args[*cur_arg + 1]) {
8277 if (err)
8278 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8279 return ERR_ALERT | ERR_FATAL;
8280 }
8281
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008282 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008283 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8284
Emeric Brunef42d922012-10-11 16:11:36 +02008285 return 0;
8286}
8287
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008288/* parse the "ssl-default-bind-options" keyword in global section */
8289static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8290 struct proxy *defpx, const char *file, int line,
8291 char **err) {
8292 int i = 1;
8293
8294 if (*(args[i]) == 0) {
8295 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8296 return -1;
8297 }
8298 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008299 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008300 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008301 else if (!strcmp(args[i], "prefer-client-ciphers"))
8302 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008303 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8304 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8305 i++;
8306 else {
8307 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8308 return -1;
8309 }
8310 }
8311 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008312 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8313 return -1;
8314 }
8315 i++;
8316 }
8317 return 0;
8318}
8319
8320/* parse the "ssl-default-server-options" keyword in global section */
8321static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8322 struct proxy *defpx, const char *file, int line,
8323 char **err) {
8324 int i = 1;
8325
8326 if (*(args[i]) == 0) {
8327 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8328 return -1;
8329 }
8330 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008331 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008332 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008333 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8334 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8335 i++;
8336 else {
8337 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8338 return -1;
8339 }
8340 }
8341 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008342 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8343 return -1;
8344 }
8345 i++;
8346 }
8347 return 0;
8348}
8349
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008350/* parse the "ca-base" / "crt-base" keywords in global section.
8351 * Returns <0 on alert, >0 on warning, 0 on success.
8352 */
8353static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8354 struct proxy *defpx, const char *file, int line,
8355 char **err)
8356{
8357 char **target;
8358
Willy Tarreauef934602016-12-22 23:12:01 +01008359 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008360
8361 if (too_many_args(1, args, err, NULL))
8362 return -1;
8363
8364 if (*target) {
8365 memprintf(err, "'%s' already specified.", args[0]);
8366 return -1;
8367 }
8368
8369 if (*(args[1]) == 0) {
8370 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8371 return -1;
8372 }
8373 *target = strdup(args[1]);
8374 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008375}
8376
8377/* parse the "ssl-mode-async" keyword in global section.
8378 * Returns <0 on alert, >0 on warning, 0 on success.
8379 */
8380static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8381 struct proxy *defpx, const char *file, int line,
8382 char **err)
8383{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008384#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008385 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008386 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008387 return 0;
8388#else
8389 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8390 return -1;
8391#endif
8392}
8393
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008394#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008395static int ssl_check_async_engine_count(void) {
8396 int err_code = 0;
8397
Emeric Brun3854e012017-05-17 20:42:48 +02008398 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008399 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008400 err_code = ERR_ABORT;
8401 }
8402 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008403}
8404
Grant Zhang872f9c22017-01-21 01:10:18 +00008405/* parse the "ssl-engine" keyword in global section.
8406 * Returns <0 on alert, >0 on warning, 0 on success.
8407 */
8408static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8409 struct proxy *defpx, const char *file, int line,
8410 char **err)
8411{
8412 char *algo;
8413 int ret = -1;
8414
8415 if (*(args[1]) == 0) {
8416 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8417 return ret;
8418 }
8419
8420 if (*(args[2]) == 0) {
8421 /* if no list of algorithms is given, it defaults to ALL */
8422 algo = strdup("ALL");
8423 goto add_engine;
8424 }
8425
8426 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8427 if (strcmp(args[2], "algo") != 0) {
8428 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8429 return ret;
8430 }
8431
8432 if (*(args[3]) == 0) {
8433 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8434 return ret;
8435 }
8436 algo = strdup(args[3]);
8437
8438add_engine:
8439 if (ssl_init_single_engine(args[1], algo)==0) {
8440 openssl_engines_initialized++;
8441 ret = 0;
8442 }
8443 free(algo);
8444 return ret;
8445}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008446#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008447
Willy Tarreauf22e9682016-12-21 23:23:19 +01008448/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8449 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8450 */
8451static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8452 struct proxy *defpx, const char *file, int line,
8453 char **err)
8454{
8455 char **target;
8456
Willy Tarreauef934602016-12-22 23:12:01 +01008457 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008458
8459 if (too_many_args(1, args, err, NULL))
8460 return -1;
8461
8462 if (*(args[1]) == 0) {
8463 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8464 return -1;
8465 }
8466
8467 free(*target);
8468 *target = strdup(args[1]);
8469 return 0;
8470}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008471
8472#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8473/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8474 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8475 */
8476static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8477 struct proxy *defpx, const char *file, int line,
8478 char **err)
8479{
8480 char **target;
8481
8482 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8483
8484 if (too_many_args(1, args, err, NULL))
8485 return -1;
8486
8487 if (*(args[1]) == 0) {
8488 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8489 return -1;
8490 }
8491
8492 free(*target);
8493 *target = strdup(args[1]);
8494 return 0;
8495}
8496#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008497
Willy Tarreau9ceda382016-12-21 23:13:03 +01008498/* parse various global tune.ssl settings consisting in positive integers.
8499 * Returns <0 on alert, >0 on warning, 0 on success.
8500 */
8501static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8502 struct proxy *defpx, const char *file, int line,
8503 char **err)
8504{
8505 int *target;
8506
8507 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8508 target = &global.tune.sslcachesize;
8509 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008510 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008511 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008512 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008513 else if (strcmp(args[0], "maxsslconn") == 0)
8514 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008515 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8516 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008517 else {
8518 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8519 return -1;
8520 }
8521
8522 if (too_many_args(1, args, err, NULL))
8523 return -1;
8524
8525 if (*(args[1]) == 0) {
8526 memprintf(err, "'%s' expects an integer argument.", args[0]);
8527 return -1;
8528 }
8529
8530 *target = atoi(args[1]);
8531 if (*target < 0) {
8532 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8533 return -1;
8534 }
8535 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008536}
8537
8538static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8539 struct proxy *defpx, const char *file, int line,
8540 char **err)
8541{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008542 int ret;
8543
8544 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8545 if (ret != 0)
8546 return ret;
8547
Willy Tarreaubafbe012017-11-24 17:34:44 +01008548 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008549 memprintf(err, "'%s' is already configured.", args[0]);
8550 return -1;
8551 }
8552
Willy Tarreaubafbe012017-11-24 17:34:44 +01008553 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8554 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008555 memprintf(err, "Out of memory error.");
8556 return -1;
8557 }
8558 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008559}
8560
8561/* parse "ssl.force-private-cache".
8562 * Returns <0 on alert, >0 on warning, 0 on success.
8563 */
8564static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8565 struct proxy *defpx, const char *file, int line,
8566 char **err)
8567{
8568 if (too_many_args(0, args, err, NULL))
8569 return -1;
8570
Willy Tarreauef934602016-12-22 23:12:01 +01008571 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008572 return 0;
8573}
8574
8575/* parse "ssl.lifetime".
8576 * Returns <0 on alert, >0 on warning, 0 on success.
8577 */
8578static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8579 struct proxy *defpx, const char *file, int line,
8580 char **err)
8581{
8582 const char *res;
8583
8584 if (too_many_args(1, args, err, NULL))
8585 return -1;
8586
8587 if (*(args[1]) == 0) {
8588 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8589 return -1;
8590 }
8591
Willy Tarreauef934602016-12-22 23:12:01 +01008592 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008593 if (res) {
8594 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8595 return -1;
8596 }
8597 return 0;
8598}
8599
8600#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008601/* parse "ssl-dh-param-file".
8602 * Returns <0 on alert, >0 on warning, 0 on success.
8603 */
8604static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8605 struct proxy *defpx, const char *file, int line,
8606 char **err)
8607{
8608 if (too_many_args(1, args, err, NULL))
8609 return -1;
8610
8611 if (*(args[1]) == 0) {
8612 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8613 return -1;
8614 }
8615
8616 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8617 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8618 return -1;
8619 }
8620 return 0;
8621}
8622
Willy Tarreau9ceda382016-12-21 23:13:03 +01008623/* parse "ssl.default-dh-param".
8624 * Returns <0 on alert, >0 on warning, 0 on success.
8625 */
8626static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8627 struct proxy *defpx, const char *file, int line,
8628 char **err)
8629{
8630 if (too_many_args(1, args, err, NULL))
8631 return -1;
8632
8633 if (*(args[1]) == 0) {
8634 memprintf(err, "'%s' expects an integer argument.", args[0]);
8635 return -1;
8636 }
8637
Willy Tarreauef934602016-12-22 23:12:01 +01008638 global_ssl.default_dh_param = atoi(args[1]);
8639 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008640 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8641 return -1;
8642 }
8643 return 0;
8644}
8645#endif
8646
8647
William Lallemand32af2032016-10-29 18:09:35 +02008648/* This function is used with TLS ticket keys management. It permits to browse
8649 * each reference. The variable <getnext> must contain the current node,
8650 * <end> point to the root node.
8651 */
8652#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8653static inline
8654struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8655{
8656 struct tls_keys_ref *ref = getnext;
8657
8658 while (1) {
8659
8660 /* Get next list entry. */
8661 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8662
8663 /* If the entry is the last of the list, return NULL. */
8664 if (&ref->list == end)
8665 return NULL;
8666
8667 return ref;
8668 }
8669}
8670
8671static inline
8672struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8673{
8674 int id;
8675 char *error;
8676
8677 /* If the reference starts by a '#', this is numeric id. */
8678 if (reference[0] == '#') {
8679 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8680 id = strtol(reference + 1, &error, 10);
8681 if (*error != '\0')
8682 return NULL;
8683
8684 /* Perform the unique id lookup. */
8685 return tlskeys_ref_lookupid(id);
8686 }
8687
8688 /* Perform the string lookup. */
8689 return tlskeys_ref_lookup(reference);
8690}
8691#endif
8692
8693
8694#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8695
8696static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8697
8698static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8699 return cli_io_handler_tlskeys_files(appctx);
8700}
8701
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008702/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8703 * (next index to be dumped), and cli.p0 (next key reference).
8704 */
William Lallemand32af2032016-10-29 18:09:35 +02008705static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8706
8707 struct stream_interface *si = appctx->owner;
8708
8709 switch (appctx->st2) {
8710 case STAT_ST_INIT:
8711 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008712 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008713 * later and restart at the state "STAT_ST_INIT".
8714 */
8715 chunk_reset(&trash);
8716
8717 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8718 chunk_appendf(&trash, "# id secret\n");
8719 else
8720 chunk_appendf(&trash, "# id (file)\n");
8721
Willy Tarreau06d80a92017-10-19 14:32:15 +02008722 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008723 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008724 return 0;
8725 }
8726
William Lallemand32af2032016-10-29 18:09:35 +02008727 /* Now, we start the browsing of the references lists.
8728 * Note that the following call to LIST_ELEM return bad pointer. The only
8729 * available field of this pointer is <list>. It is used with the function
8730 * tlskeys_list_get_next() for retruning the first available entry
8731 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008732 if (appctx->ctx.cli.p0 == NULL) {
8733 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8734 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008735 }
8736
8737 appctx->st2 = STAT_ST_LIST;
8738 /* fall through */
8739
8740 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008741 while (appctx->ctx.cli.p0) {
8742 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008743
8744 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008745 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008746 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008747
8748 if (appctx->ctx.cli.i1 == 0)
8749 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8750
William Lallemand32af2032016-10-29 18:09:35 +02008751 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008752 int head;
8753
8754 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8755 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008756 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008757 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008758
8759 chunk_reset(t2);
8760 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008761 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8762 sizeof(struct tls_sess_key),
8763 t2->area, t2->size);
8764 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8765 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008766
Willy Tarreau06d80a92017-10-19 14:32:15 +02008767 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008768 /* let's try again later from this stream. We add ourselves into
8769 * this stream's users so that it can remove us upon termination.
8770 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008771 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008772 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008773 return 0;
8774 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008775 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008776 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008777 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008778 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008779 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008780 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008781 /* let's try again later from this stream. We add ourselves into
8782 * this stream's users so that it can remove us upon termination.
8783 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008784 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008785 return 0;
8786 }
8787
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008788 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008789 break;
8790
8791 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008792 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008793 }
8794
8795 appctx->st2 = STAT_ST_FIN;
8796 /* fall through */
8797
8798 default:
8799 appctx->st2 = STAT_ST_FIN;
8800 return 1;
8801 }
8802 return 0;
8803}
8804
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008805/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008806static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008807{
William Lallemand32af2032016-10-29 18:09:35 +02008808 /* no parameter, shows only file list */
8809 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008810 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008811 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008812 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008813 }
8814
8815 if (args[2][0] == '*') {
8816 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008817 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008818 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008819 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8820 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008821 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008822 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008823 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008824 return 1;
8825 }
8826 }
William Lallemand32af2032016-10-29 18:09:35 +02008827 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008828 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008829}
8830
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008831static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008832{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008833 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008834 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008835
William Lallemand32af2032016-10-29 18:09:35 +02008836 /* Expect two parameters: the filename and the new new TLS key in encoding */
8837 if (!*args[3] || !*args[4]) {
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' expects a filename and the new TLS key in base64 encoding.\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 Tarreauf5f26e82016-12-16 18:47:27 +01008844 ref = tlskeys_ref_lookup_ref(args[3]);
8845 if (!ref) {
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' unable to locate referenced filename\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 }
8851
Willy Tarreau1c913e42018-08-22 05:26:57 +02008852 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8853 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008854 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008855 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008856 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008857 return 1;
8858 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008859 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008860 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008861 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008862 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008863 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008864 return 1;
8865
8866}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008867#endif
William Lallemand32af2032016-10-29 18:09:35 +02008868
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008869static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008870{
8871#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8872 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008873 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008874
8875 if (!payload)
8876 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008877
8878 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008879 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008880 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008881 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008882 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008883 return 1;
8884 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008885
8886 /* remove \r and \n from the payload */
8887 for (i = 0, j = 0; payload[i]; i++) {
8888 if (payload[i] == '\r' || payload[i] == '\n')
8889 continue;
8890 payload[j++] = payload[i];
8891 }
8892 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008893
Willy Tarreau1c913e42018-08-22 05:26:57 +02008894 ret = base64dec(payload, j, trash.area, trash.size);
8895 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008896 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008897 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008898 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008899 return 1;
8900 }
8901
Willy Tarreau1c913e42018-08-22 05:26:57 +02008902 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008903 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8904 if (err) {
8905 memprintf(&err, "%s.\n", err);
8906 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008907 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008908 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008909 else {
8910 appctx->ctx.cli.severity = LOG_ERR;
8911 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8912 appctx->st0 = CLI_ST_PRINT;
8913 }
William Lallemand32af2032016-10-29 18:09:35 +02008914 return 1;
8915 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008916 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008917 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008918 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008919 return 1;
8920#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008921 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008922 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 +01008923 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008924 return 1;
8925#endif
8926
8927}
8928
8929/* register cli keywords */
8930static struct cli_kw_list cli_kws = {{ },{
8931#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8932 { { "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 +02008933 { { "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 +02008934#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008935 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008936 { { NULL }, NULL, NULL, NULL }
8937}};
8938
Willy Tarreau0108d902018-11-25 19:14:37 +01008939INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008940
Willy Tarreau7875d092012-09-10 08:20:03 +02008941/* Note: must not be declared <const> as its list will be overwritten.
8942 * Please take care of keeping this list alphabetically sorted.
8943 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008944static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008945 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008946 { "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 +01008947#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01008948 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008949#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008950 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008951#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8952 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8953#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008954 { "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 +02008955 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008956 { "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 +02008957 { "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 -04008958#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008959 { "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 -04008960#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008961#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8962 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8963#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008964 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8965 { "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 +01008966 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008967 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008968 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8969 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8970 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8971 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8972 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8973 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8974 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8975 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008976 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008977 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8978 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008979 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008980 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8981 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8982 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8983 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8984 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8985 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8986 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008987 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008988 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008989 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008990 { "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 +01008991 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008992 { "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 +02008993 { "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 +01008994 { "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 +02008995 { "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 +01008996#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008997 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008998#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008999#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009000 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009001#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009002 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009003#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009004 { "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 -04009005#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009006 { "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 -04009007#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009008 { "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 -04009009#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009010#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9011 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9012#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009013#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009014 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009015#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009016 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9017 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9018 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9019 { "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 +02009020 { NULL, NULL, 0, 0, 0 },
9021}};
9022
Willy Tarreau0108d902018-11-25 19:14:37 +01009023INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9024
Willy Tarreau7875d092012-09-10 08:20:03 +02009025/* Note: must not be declared <const> as its list will be overwritten.
9026 * Please take care of keeping this list alphabetically sorted.
9027 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009028static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009029 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9030 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009031 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009032}};
9033
Willy Tarreau0108d902018-11-25 19:14:37 +01009034INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9035
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009036/* Note: must not be declared <const> as its list will be overwritten.
9037 * Please take care of keeping this list alphabetically sorted, doing so helps
9038 * all code contributors.
9039 * Optional keywords are also declared with a NULL ->parse() function so that
9040 * the config parser can report an appropriate error when a known keyword was
9041 * not enabled.
9042 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009043static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009044 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009045 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9046 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9047 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009048#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9049 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9050#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009051 { "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 +01009052 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009053 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009054 { "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 +01009055 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009056 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9057 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009058 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9059 { NULL, NULL, 0 },
9060};
9061
Willy Tarreau0108d902018-11-25 19:14:37 +01009062/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9063
Willy Tarreau51fb7652012-09-18 18:24:39 +02009064static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009065 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009066 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9067 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9068 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9069 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9070 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9071 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009072#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9073 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9074#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009075 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9076 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9077 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9078 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9079 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9080 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9081 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9082 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9083 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9084 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009085 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009086 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009087 { "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 +02009088 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9089 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9090 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9091 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009092 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009093 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9094 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009095 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9096 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009097 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9098 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9099 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9100 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9101 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009102 { NULL, NULL, 0 },
9103}};
Emeric Brun46591952012-05-18 15:47:34 +02009104
Willy Tarreau0108d902018-11-25 19:14:37 +01009105INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9106
Willy Tarreau92faadf2012-10-10 23:04:25 +02009107/* Note: must not be declared <const> as its list will be overwritten.
9108 * Please take care of keeping this list alphabetically sorted, doing so helps
9109 * all code contributors.
9110 * Optional keywords are also declared with a NULL ->parse() function so that
9111 * the config parser can report an appropriate error when a known keyword was
9112 * not enabled.
9113 */
9114static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009115 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009116 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009117 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009118 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009119 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9120 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009121#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9122 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9123#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009124 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9125 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9126 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9127 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9128 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9129 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9130 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9131 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9132 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9133 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9134 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9135 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9136 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9137 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9138 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9139 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9140 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9141 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009142 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009143 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9144 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9145 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9146 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9147 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9148 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9149 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9150 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9151 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9152 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009153 { NULL, NULL, 0, 0 },
9154}};
9155
Willy Tarreau0108d902018-11-25 19:14:37 +01009156INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9157
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009158static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009159 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9160 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009161 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009162 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9163 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009164#ifndef OPENSSL_NO_DH
9165 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9166#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009167 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009168#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009169 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009170#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009171 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9172#ifndef OPENSSL_NO_DH
9173 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9174#endif
9175 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9176 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9177 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9178 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009179 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009180 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9181 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009182#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9183 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9184 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9185#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009186 { 0, NULL, NULL },
9187}};
9188
Willy Tarreau0108d902018-11-25 19:14:37 +01009189INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9190
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009191/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009192static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009193 .snd_buf = ssl_sock_from_buf,
9194 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009195 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009196 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009197 .rcv_pipe = NULL,
9198 .snd_pipe = NULL,
9199 .shutr = NULL,
9200 .shutw = ssl_sock_shutw,
9201 .close = ssl_sock_close,
9202 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009203 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009204 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009205 .prepare_srv = ssl_sock_prepare_srv_ctx,
9206 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009207 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009208 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009209};
9210
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009211enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9212 struct session *sess, struct stream *s, int flags)
9213{
9214 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009215 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009216
9217 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009218 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009219
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009220 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009221 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009222 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009223 s->req.flags |= CF_READ_NULL;
9224 return ACT_RET_YIELD;
9225 }
9226 }
9227 return (ACT_RET_CONT);
9228}
9229
9230static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9231{
9232 rule->action_ptr = ssl_action_wait_for_hs;
9233
9234 return ACT_RET_PRS_OK;
9235}
9236
9237static struct action_kw_list http_req_actions = {ILH, {
9238 { "wait-for-handshake", ssl_parse_wait_for_hs },
9239 { /* END */ }
9240}};
9241
Willy Tarreau0108d902018-11-25 19:14:37 +01009242INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9243
Daniel Jakots54ffb912015-11-06 20:02:41 +01009244#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009245
9246static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9247{
9248 if (ptr) {
9249 chunk_destroy(ptr);
9250 free(ptr);
9251 }
9252}
9253
9254#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009255static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9256{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009257 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009258}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009259
Emeric Brun46591952012-05-18 15:47:34 +02009260__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009261static void __ssl_sock_init(void)
9262{
Emeric Brun46591952012-05-18 15:47:34 +02009263 STACK_OF(SSL_COMP)* cm;
9264
Willy Tarreauef934602016-12-22 23:12:01 +01009265 if (global_ssl.listen_default_ciphers)
9266 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9267 if (global_ssl.connect_default_ciphers)
9268 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009269#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9270 if (global_ssl.listen_default_ciphersuites)
9271 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9272 if (global_ssl.connect_default_ciphersuites)
9273 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9274#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009275
Willy Tarreau13e14102016-12-22 20:25:26 +01009276 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009277 SSL_library_init();
9278 cm = SSL_COMP_get_compression_methods();
9279 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009280#ifdef USE_THREAD
9281 ssl_locking_init();
9282#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009283#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009284 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9285#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009286 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009287 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 +01009288 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009289#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009290 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009291 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009292#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009293#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9294 hap_register_post_check(tlskeys_finalize_config);
9295#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009296
9297 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9298 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9299
9300#ifndef OPENSSL_NO_DH
9301 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9302 hap_register_post_deinit(ssl_free_dh);
9303#endif
9304#ifndef OPENSSL_NO_ENGINE
9305 hap_register_post_deinit(ssl_free_engines);
9306#endif
9307 /* Load SSL string for the verbose & debug mode. */
9308 ERR_load_SSL_strings();
9309}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009310
Willy Tarreau80713382018-11-26 10:19:54 +01009311/* Compute and register the version string */
9312static void ssl_register_build_options()
9313{
9314 char *ptr = NULL;
9315 int i;
9316
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009317 memprintf(&ptr, "Built with OpenSSL version : "
9318#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009319 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009320#else /* OPENSSL_IS_BORINGSSL */
9321 OPENSSL_VERSION_TEXT
9322 "\nRunning on OpenSSL version : %s%s",
9323 SSLeay_version(SSLEAY_VERSION),
9324 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9325#endif
9326 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9327#if OPENSSL_VERSION_NUMBER < 0x00907000L
9328 "no (library version too old)"
9329#elif defined(OPENSSL_NO_TLSEXT)
9330 "no (disabled via OPENSSL_NO_TLSEXT)"
9331#else
9332 "yes"
9333#endif
9334 "", ptr);
9335
9336 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9337#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9338 "yes"
9339#else
9340#ifdef OPENSSL_NO_TLSEXT
9341 "no (because of OPENSSL_NO_TLSEXT)"
9342#else
9343 "no (version might be too old, 0.9.8f min needed)"
9344#endif
9345#endif
9346 "", ptr);
9347
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009348 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9349 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9350 if (methodVersions[i].option)
9351 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009352
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009353 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009354}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009355
Willy Tarreau80713382018-11-26 10:19:54 +01009356INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009357
Emeric Brun46591952012-05-18 15:47:34 +02009358
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009359#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009360void ssl_free_engines(void) {
9361 struct ssl_engine_list *wl, *wlb;
9362 /* free up engine list */
9363 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9364 ENGINE_finish(wl->e);
9365 ENGINE_free(wl->e);
9366 LIST_DEL(&wl->list);
9367 free(wl);
9368 }
9369}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009370#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009371
Remi Gacogned3a23c32015-05-28 16:39:47 +02009372#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009373void ssl_free_dh(void) {
9374 if (local_dh_1024) {
9375 DH_free(local_dh_1024);
9376 local_dh_1024 = NULL;
9377 }
9378 if (local_dh_2048) {
9379 DH_free(local_dh_2048);
9380 local_dh_2048 = NULL;
9381 }
9382 if (local_dh_4096) {
9383 DH_free(local_dh_4096);
9384 local_dh_4096 = NULL;
9385 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009386 if (global_dh) {
9387 DH_free(global_dh);
9388 global_dh = NULL;
9389 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009390}
9391#endif
9392
9393__attribute__((destructor))
9394static void __ssl_sock_deinit(void)
9395{
9396#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009397 if (ssl_ctx_lru_tree) {
9398 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009399 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009400 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009401#endif
9402
9403 ERR_remove_state(0);
9404 ERR_free_strings();
9405
9406 EVP_cleanup();
9407
9408#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9409 CRYPTO_cleanup_all_ex_data();
9410#endif
9411}
9412
9413
Emeric Brun46591952012-05-18 15:47:34 +02009414/*
9415 * Local variables:
9416 * c-indent-level: 8
9417 * c-basic-offset: 8
9418 * End:
9419 */