blob: 86d4f227a47a77616043b160cc746669d8f66136 [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
1564 * 28 bytes for unix payload, and them 1 byte for the session id. So
1565 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1566 */
1567 msg += 1 + 1 + 4 + 28 + 1;
1568 if (msg > end)
1569 return;
1570
1571 /* Next two bytes are the ciphersuite length. */
1572 if (msg + 2 > end)
1573 return;
1574 rec_len = (msg[0] << 8) + msg[1];
1575 msg += 2;
1576 if (msg + rec_len > end || msg + rec_len < msg)
1577 return;
1578
Willy Tarreaubafbe012017-11-24 17:34:44 +01001579 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001580 if (!capture)
1581 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001582 /* Compute the xxh64 of the ciphersuite. */
1583 capture->xxh64 = XXH64(msg, rec_len, 0);
1584
1585 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001586 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1587 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001588 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001589
1590 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001591}
1592
Emeric Brun29f037d2014-04-25 19:05:36 +02001593/* Callback is called for ssl protocol analyse */
1594void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1595{
Emeric Brun29f037d2014-04-25 19:05:36 +02001596#ifdef TLS1_RT_HEARTBEAT
1597 /* test heartbeat received (write_p is set to 0
1598 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001599 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001600 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001601 const unsigned char *p = buf;
1602 unsigned int payload;
1603
Emeric Brun29f037d2014-04-25 19:05:36 +02001604 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001605
1606 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1607 if (*p != TLS1_HB_REQUEST)
1608 return;
1609
Willy Tarreauaeed6722014-04-25 23:59:58 +02001610 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001611 goto kill_it;
1612
1613 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001614 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001615 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001616 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001617 /* We have a clear heartbleed attack (CVE-2014-0160), the
1618 * advertised payload is larger than the advertised packet
1619 * length, so we have garbage in the buffer between the
1620 * payload and the end of the buffer (p+len). We can't know
1621 * if the SSL stack is patched, and we don't know if we can
1622 * safely wipe out the area between p+3+len and payload.
1623 * So instead, we prevent the response from being sent by
1624 * setting the max_send_fragment to 0 and we report an SSL
1625 * error, which will kill this connection. It will be reported
1626 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001627 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1628 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001629 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001630 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1631 return;
1632 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001633#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001634 if (global_ssl.capture_cipherlist > 0)
1635 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001636}
1637
Bernard Spil13c53f82018-02-15 13:34:58 +01001638#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001639static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1640 const unsigned char *in, unsigned int inlen,
1641 void *arg)
1642{
1643 struct server *srv = arg;
1644
1645 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1646 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1647 return SSL_TLSEXT_ERR_OK;
1648 return SSL_TLSEXT_ERR_NOACK;
1649}
1650#endif
1651
1652#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001653/* This callback is used so that the server advertises the list of
1654 * negociable protocols for NPN.
1655 */
1656static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1657 unsigned int *len, void *arg)
1658{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001659 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001660
1661 *data = (const unsigned char *)conf->npn_str;
1662 *len = conf->npn_len;
1663 return SSL_TLSEXT_ERR_OK;
1664}
1665#endif
1666
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001667#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001668/* This callback is used so that the server advertises the list of
1669 * negociable protocols for ALPN.
1670 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001671static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1672 unsigned char *outlen,
1673 const unsigned char *server,
1674 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001675{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001676 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001677
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001678 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1679 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1680 return SSL_TLSEXT_ERR_NOACK;
1681 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001682 return SSL_TLSEXT_ERR_OK;
1683}
1684#endif
1685
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001686#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001687#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001688
Christopher Faulet30548802015-06-11 13:39:32 +02001689/* Create a X509 certificate with the specified servername and serial. This
1690 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001691static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001692ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001693{
Christopher Faulet7969a332015-10-09 11:15:03 +02001694 X509 *cacert = bind_conf->ca_sign_cert;
1695 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001696 SSL_CTX *ssl_ctx = NULL;
1697 X509 *newcrt = NULL;
1698 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001699 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001700 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001701 X509_NAME *name;
1702 const EVP_MD *digest;
1703 X509V3_CTX ctx;
1704 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001705 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001706
Christopher Faulet48a83322017-07-28 16:56:09 +02001707 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001708#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1709 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1710#else
1711 tmp_ssl = SSL_new(bind_conf->default_ctx);
1712 if (tmp_ssl)
1713 pkey = SSL_get_privatekey(tmp_ssl);
1714#endif
1715 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001716 goto mkcert_error;
1717
1718 /* Create the certificate */
1719 if (!(newcrt = X509_new()))
1720 goto mkcert_error;
1721
1722 /* Set version number for the certificate (X509v3) and the serial
1723 * number */
1724 if (X509_set_version(newcrt, 2L) != 1)
1725 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001726 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001727
1728 /* Set duration for the certificate */
1729 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1730 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1731 goto mkcert_error;
1732
1733 /* set public key in the certificate */
1734 if (X509_set_pubkey(newcrt, pkey) != 1)
1735 goto mkcert_error;
1736
1737 /* Set issuer name from the CA */
1738 if (!(name = X509_get_subject_name(cacert)))
1739 goto mkcert_error;
1740 if (X509_set_issuer_name(newcrt, name) != 1)
1741 goto mkcert_error;
1742
1743 /* Set the subject name using the same, but the CN */
1744 name = X509_NAME_dup(name);
1745 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1746 (const unsigned char *)servername,
1747 -1, -1, 0) != 1) {
1748 X509_NAME_free(name);
1749 goto mkcert_error;
1750 }
1751 if (X509_set_subject_name(newcrt, name) != 1) {
1752 X509_NAME_free(name);
1753 goto mkcert_error;
1754 }
1755 X509_NAME_free(name);
1756
1757 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001758 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001759 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1760 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1761 X509_EXTENSION *ext;
1762
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001763 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001764 goto mkcert_error;
1765 if (!X509_add_ext(newcrt, ext, -1)) {
1766 X509_EXTENSION_free(ext);
1767 goto mkcert_error;
1768 }
1769 X509_EXTENSION_free(ext);
1770 }
1771
1772 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001773
1774 key_type = EVP_PKEY_base_id(capkey);
1775
1776 if (key_type == EVP_PKEY_DSA)
1777 digest = EVP_sha1();
1778 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001779 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001780 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001781 digest = EVP_sha256();
1782 else {
Emmanuel Hocdet747ca612018-10-01 18:45:19 +02001783#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001784 int nid;
1785
1786 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1787 goto mkcert_error;
1788 if (!(digest = EVP_get_digestbynid(nid)))
1789 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001790#else
1791 goto mkcert_error;
1792#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001793 }
1794
Christopher Faulet31af49d2015-06-09 17:29:50 +02001795 if (!(X509_sign(newcrt, capkey, digest)))
1796 goto mkcert_error;
1797
1798 /* Create and set the new SSL_CTX */
1799 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1800 goto mkcert_error;
1801 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1802 goto mkcert_error;
1803 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1804 goto mkcert_error;
1805 if (!SSL_CTX_check_private_key(ssl_ctx))
1806 goto mkcert_error;
1807
1808 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001809
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001810#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001811 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001812#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001813#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1814 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001815 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001816 EC_KEY *ecc;
1817 int nid;
1818
1819 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1820 goto end;
1821 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1822 goto end;
1823 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1824 EC_KEY_free(ecc);
1825 }
1826#endif
1827 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001828 return ssl_ctx;
1829
1830 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001831 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001832 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001833 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1834 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001835 return NULL;
1836}
1837
Christopher Faulet7969a332015-10-09 11:15:03 +02001838SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001839ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001840{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001841 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001842
1843 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001844}
1845
Christopher Faulet30548802015-06-11 13:39:32 +02001846/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001847 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001848SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001849ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001850{
1851 struct lru64 *lru = NULL;
1852
1853 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001854 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001855 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001856 if (lru && lru->domain) {
1857 if (ssl)
1858 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001859 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001860 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001861 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001862 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001863 }
1864 return NULL;
1865}
1866
Emeric Brun821bb9b2017-06-15 16:37:39 +02001867/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1868 * function is not thread-safe, it should only be used to check if a certificate
1869 * exists in the lru cache (with no warranty it will not be removed by another
1870 * thread). It is kept for backward compatibility. */
1871SSL_CTX *
1872ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1873{
1874 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1875}
1876
Christopher Fauletd2cab922015-07-28 16:03:47 +02001877/* Set a certificate int the LRU cache used to store generated
1878 * certificate. Return 0 on success, otherwise -1 */
1879int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001880ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001881{
1882 struct lru64 *lru = NULL;
1883
1884 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001885 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001886 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001887 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001888 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001889 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001890 }
Christopher Faulet30548802015-06-11 13:39:32 +02001891 if (lru->domain && lru->data)
1892 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001893 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001894 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001895 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001896 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001897 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001898}
1899
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001900/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001901unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001902ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001903{
1904 return XXH32(data, len, ssl_ctx_lru_seed);
1905}
1906
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001907/* Generate a cert and immediately assign it to the SSL session so that the cert's
1908 * refcount is maintained regardless of the cert's presence in the LRU cache.
1909 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001910static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001911ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001912{
1913 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001914 SSL_CTX *ssl_ctx = NULL;
1915 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001916 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001917
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001918 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001919 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001920 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001921 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001922 if (lru && lru->domain)
1923 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001924 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001925 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001926 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001927 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001928 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001929 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001930 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001931 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001932 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001933 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001934 SSL_set_SSL_CTX(ssl, ssl_ctx);
1935 /* No LRU cache, this CTX will be released as soon as the session dies */
1936 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001937 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001938 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001939 return 0;
1940}
1941static int
1942ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1943{
1944 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001945 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001946
1947 conn_get_to_addr(conn);
1948 if (conn->flags & CO_FL_ADDR_TO_SET) {
1949 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001950 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001951 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001952 }
1953 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001954}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001955#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001956
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001957
1958#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1959#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1960#endif
1961
1962#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1963#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1964#define SSL_renegotiate_pending(arg) 0
1965#endif
1966#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1967#define SSL_OP_SINGLE_ECDH_USE 0
1968#endif
1969#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1970#define SSL_OP_NO_TICKET 0
1971#endif
1972#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1973#define SSL_OP_NO_COMPRESSION 0
1974#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001975#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1976#undef SSL_OP_NO_SSLv3
1977#define SSL_OP_NO_SSLv3 0
1978#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001979#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1980#define SSL_OP_NO_TLSv1_1 0
1981#endif
1982#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1983#define SSL_OP_NO_TLSv1_2 0
1984#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001985#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001986#define SSL_OP_NO_TLSv1_3 0
1987#endif
1988#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1989#define SSL_OP_SINGLE_DH_USE 0
1990#endif
1991#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1992#define SSL_OP_SINGLE_ECDH_USE 0
1993#endif
1994#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1995#define SSL_MODE_RELEASE_BUFFERS 0
1996#endif
1997#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1998#define SSL_MODE_SMALL_BUFFERS 0
1999#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02002000#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
2001#define SSL_OP_PRIORITIZE_CHACHA 0
2002#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002003
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002004#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002005typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2006
2007static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002008{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002009#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002010 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002011 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2012#endif
2013}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2015 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002016 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2017}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002018static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002019#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002020 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002021 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2022#endif
2023}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002024static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002026 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002027 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2028#endif
2029}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002030/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002031static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2032/* Unusable in this context. */
2033static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2034static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2035static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2036static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2037static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002038#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002039typedef enum { SET_MIN, SET_MAX } set_context_func;
2040
2041static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2042 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002043 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2044}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002045static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2046 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2047 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2048}
2049static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2050 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002051 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2052}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002053static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2054 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2055 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2056}
2057static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2058 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002059 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2060}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002061static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2062 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2063 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2064}
2065static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2066 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002067 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2068}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002069static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2070 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2071 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2072}
2073static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002074#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002075 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002076 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2077#endif
2078}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002079static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2080#if SSL_OP_NO_TLSv1_3
2081 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2082 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002083#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002084}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002085#endif
2086static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2087static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002088
2089static struct {
2090 int option;
2091 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002092 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2093 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002094 const char *name;
2095} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002096 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2097 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2098 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2099 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2100 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2101 {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002102};
2103
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002104static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2105{
2106 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2107 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2108 SSL_set_SSL_CTX(ssl, ctx);
2109}
2110
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002111#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002112
2113static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2114{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002115 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002117
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002118 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2119 return SSL_TLSEXT_ERR_OK;
2120 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121}
2122
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002123#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002124static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2125{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002126 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002127#else
2128static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2129{
2130#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002131 struct connection *conn;
2132 struct bind_conf *s;
2133 const uint8_t *extension_data;
2134 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002135 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002136
2137 char *wildp = NULL;
2138 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002139 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002141 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002142 int i;
2143
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002144 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002145 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146
Olivier Houchard9679ac92017-10-27 14:58:08 +02002147 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002148 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002149#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002150 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2151 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002152#else
2153 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2154#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002155 /*
2156 * The server_name extension was given too much extensibility when it
2157 * was written, so parsing the normal case is a bit complex.
2158 */
2159 size_t len;
2160 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002161 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002162 /* Extract the length of the supplied list of names. */
2163 len = (*extension_data++) << 8;
2164 len |= *extension_data++;
2165 if (len + 2 != extension_len)
2166 goto abort;
2167 /*
2168 * The list in practice only has a single element, so we only consider
2169 * the first one.
2170 */
2171 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2172 goto abort;
2173 extension_len = len - 1;
2174 /* Now we can finally pull out the byte array with the actual hostname. */
2175 if (extension_len <= 2)
2176 goto abort;
2177 len = (*extension_data++) << 8;
2178 len |= *extension_data++;
2179 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2180 || memchr(extension_data, 0, len) != NULL)
2181 goto abort;
2182 servername = extension_data;
2183 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002184 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002185#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2186 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002187 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002188 }
2189#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002190 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002191 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002192 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002193 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002194 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002195 goto abort;
2196 }
2197
2198 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002199#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002200 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002201#else
2202 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2203#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002204 uint8_t sign;
2205 size_t len;
2206 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002207 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 len = (*extension_data++) << 8;
2209 len |= *extension_data++;
2210 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002211 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002212 if (len % 2 != 0)
2213 goto abort;
2214 for (; len > 0; len -= 2) {
2215 extension_data++; /* hash */
2216 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002217 switch (sign) {
2218 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002219 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002220 break;
2221 case TLSEXT_signature_ecdsa:
2222 has_ecdsa_sig = 1;
2223 break;
2224 default:
2225 continue;
2226 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002227 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002228 break;
2229 }
2230 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002231 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002232 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233 }
2234 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002235 const SSL_CIPHER *cipher;
2236 size_t len;
2237 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002238 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002239#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002240 len = ctx->cipher_suites_len;
2241 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002242#else
2243 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2244#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002245 if (len % 2 != 0)
2246 goto abort;
2247 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002248#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002250 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002251#else
2252 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2253#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002254 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002255 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002256 break;
2257 }
2258 }
2259 }
2260
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002261 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002262 trash.area[i] = tolower(servername[i]);
2263 if (!wildp && (trash.area[i] == '.'))
2264 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002265 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002266 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002267
2268 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002269 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002270
2271 /* lookup a not neg filter */
2272 for (n = node; n; n = ebmb_next_dup(n)) {
2273 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002274 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002275 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002276 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002277 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002278 break;
2279 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002280 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002281 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002282 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002283 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002284 if (!node_anonymous)
2285 node_anonymous = n;
2286 break;
2287 }
2288 }
2289 }
2290 if (wildp) {
2291 /* lookup in wildcards names */
2292 node = ebst_lookup(&s->sni_w_ctx, wildp);
2293 for (n = node; n; n = ebmb_next_dup(n)) {
2294 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002295 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002296 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002297 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002298 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 break;
2300 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002301 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002302 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002303 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002304 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 if (!node_anonymous)
2306 node_anonymous = n;
2307 break;
2308 }
2309 }
2310 }
2311 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002312 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002313 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2314 : ((has_rsa_sig && node_rsa) ? node_rsa
2315 : (node_anonymous ? node_anonymous
2316 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2317 : node_rsa /* no rsa signature case (far far away) */
2318 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002319 if (node) {
2320 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002321 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002322 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002323 if (conf) {
2324 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2325 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2326 if (conf->early_data)
2327 allow_early = 1;
2328 }
2329 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002330 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002331#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002332 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002333 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002334 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002335 }
2336#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002337 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002338 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002339 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002340 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002341allow_early:
2342#ifdef OPENSSL_IS_BORINGSSL
2343 if (allow_early)
2344 SSL_set_early_data_enabled(ssl, 1);
2345#else
2346 if (!allow_early)
2347 SSL_set_max_early_data(ssl, 0);
2348#endif
2349 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002350 abort:
2351 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2352 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002353#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002354 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002355#else
2356 *al = SSL_AD_UNRECOGNIZED_NAME;
2357 return 0;
2358#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359}
2360
2361#else /* OPENSSL_IS_BORINGSSL */
2362
Emeric Brunfc0421f2012-09-07 17:30:07 +02002363/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2364 * warning when no match is found, which implies the default (first) cert
2365 * will keep being used.
2366 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002367static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002368{
2369 const char *servername;
2370 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002371 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002372 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002373 int i;
2374 (void)al; /* shut gcc stupid warning */
2375
2376 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002377 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002378#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002379 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2380 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002381#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002382 if (s->strict_sni)
2383 return SSL_TLSEXT_ERR_ALERT_FATAL;
2384 ssl_sock_switchctx_set(ssl, s->default_ctx);
2385 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002386 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002387
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002388 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002389 if (!servername[i])
2390 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002391 trash.area[i] = tolower(servername[i]);
2392 if (!wildp && (trash.area[i] == '.'))
2393 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002394 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002395 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002396
2397 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002398 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002399
2400 /* lookup a not neg filter */
2401 for (n = node; n; n = ebmb_next_dup(n)) {
2402 if (!container_of(n, struct sni_ctx, name)->neg) {
2403 node = n;
2404 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002405 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002406 }
2407 if (!node && wildp) {
2408 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002409 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002410 }
2411 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002412#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002413 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2414 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002415 return SSL_TLSEXT_ERR_OK;
2416 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002417#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002418 if (s->strict_sni)
2419 return SSL_TLSEXT_ERR_ALERT_FATAL;
2420 ssl_sock_switchctx_set(ssl, s->default_ctx);
2421 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002422 }
2423
2424 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002425 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002426 return SSL_TLSEXT_ERR_OK;
2427}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002428#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002429#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2430
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002431#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002432
2433static DH * ssl_get_dh_1024(void)
2434{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002435 static unsigned char dh1024_p[]={
2436 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2437 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2438 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2439 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2440 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2441 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2442 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2443 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2444 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2445 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2446 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2447 };
2448 static unsigned char dh1024_g[]={
2449 0x02,
2450 };
2451
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002452 BIGNUM *p;
2453 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002454 DH *dh = DH_new();
2455 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002456 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2457 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002458
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002459 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002460 DH_free(dh);
2461 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002462 } else {
2463 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002464 }
2465 }
2466 return dh;
2467}
2468
2469static DH *ssl_get_dh_2048(void)
2470{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002471 static unsigned char dh2048_p[]={
2472 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2473 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2474 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2475 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2476 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2477 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2478 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2479 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2480 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2481 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2482 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2483 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2484 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2485 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2486 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2487 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2488 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2489 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2490 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2491 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2492 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2493 0xB7,0x1F,0x77,0xF3,
2494 };
2495 static unsigned char dh2048_g[]={
2496 0x02,
2497 };
2498
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002499 BIGNUM *p;
2500 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002501 DH *dh = DH_new();
2502 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002503 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2504 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002505
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002506 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002507 DH_free(dh);
2508 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002509 } else {
2510 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002511 }
2512 }
2513 return dh;
2514}
2515
2516static DH *ssl_get_dh_4096(void)
2517{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002518 static unsigned char dh4096_p[]={
2519 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2520 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2521 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2522 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2523 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2524 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2525 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2526 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2527 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2528 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2529 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2530 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2531 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2532 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2533 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2534 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2535 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2536 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2537 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2538 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2539 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2540 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2541 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2542 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2543 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2544 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2545 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2546 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2547 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2548 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2549 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2550 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2551 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2552 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2553 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2554 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2555 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2556 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2557 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2558 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2559 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2560 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2561 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002562 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002563 static unsigned char dh4096_g[]={
2564 0x02,
2565 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002566
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002567 BIGNUM *p;
2568 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002569 DH *dh = DH_new();
2570 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002571 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2572 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002573
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002574 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002575 DH_free(dh);
2576 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002577 } else {
2578 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002579 }
2580 }
2581 return dh;
2582}
2583
2584/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002585 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002586static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2587{
2588 DH *dh = NULL;
2589 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002590 int type;
2591
2592 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002593
2594 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2595 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2596 */
2597 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2598 keylen = EVP_PKEY_bits(pkey);
2599 }
2600
Willy Tarreauef934602016-12-22 23:12:01 +01002601 if (keylen > global_ssl.default_dh_param) {
2602 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002603 }
2604
Remi Gacogned3a341a2015-05-29 16:26:17 +02002605 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002606 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002607 }
2608 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002609 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002610 }
2611 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002612 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002613 }
2614
2615 return dh;
2616}
2617
Remi Gacogne47783ef2015-05-29 15:53:22 +02002618static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002619{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002620 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002621 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002622
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002623 if (in == NULL)
2624 goto end;
2625
Remi Gacogne47783ef2015-05-29 15:53:22 +02002626 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002627 goto end;
2628
Remi Gacogne47783ef2015-05-29 15:53:22 +02002629 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2630
2631end:
2632 if (in)
2633 BIO_free(in);
2634
Emeric Brune1b4ed42018-08-16 15:14:12 +02002635 ERR_clear_error();
2636
Remi Gacogne47783ef2015-05-29 15:53:22 +02002637 return dh;
2638}
2639
2640int ssl_sock_load_global_dh_param_from_file(const char *filename)
2641{
2642 global_dh = ssl_sock_get_dh_from_file(filename);
2643
2644 if (global_dh) {
2645 return 0;
2646 }
2647
2648 return -1;
2649}
2650
2651/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002652 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002653int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2654{
2655 int ret = -1;
2656 DH *dh = ssl_sock_get_dh_from_file(file);
2657
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002658 if (dh) {
2659 ret = 1;
2660 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002661
2662 if (ssl_dh_ptr_index >= 0) {
2663 /* store a pointer to the DH params to avoid complaining about
2664 ssl-default-dh-param not being set for this SSL_CTX */
2665 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2666 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002667 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002668 else if (global_dh) {
2669 SSL_CTX_set_tmp_dh(ctx, global_dh);
2670 ret = 0; /* DH params not found */
2671 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002672 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002673 /* Clear openssl global errors stack */
2674 ERR_clear_error();
2675
Willy Tarreauef934602016-12-22 23:12:01 +01002676 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002677 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002678 if (local_dh_1024 == NULL)
2679 local_dh_1024 = ssl_get_dh_1024();
2680
Remi Gacogne8de54152014-07-15 11:36:40 +02002681 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002682 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002683
Remi Gacogne8de54152014-07-15 11:36:40 +02002684 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002685 }
2686 else {
2687 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2688 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002689
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002690 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002691 }
Emeric Brun644cde02012-12-14 11:21:13 +01002692
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002693end:
2694 if (dh)
2695 DH_free(dh);
2696
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002697 return ret;
2698}
2699#endif
2700
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002701static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002702 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002703{
2704 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002705 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002706 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002707
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002708 if (*name == '!') {
2709 neg = 1;
2710 name++;
2711 }
2712 if (*name == '*') {
2713 wild = 1;
2714 name++;
2715 }
2716 /* !* filter is a nop */
2717 if (neg && wild)
2718 return order;
2719 if (*name) {
2720 int j, len;
2721 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002722 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002723 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002724 if (j >= trash.size)
2725 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002726 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002727
2728 /* Check for duplicates. */
2729 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002730 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002731 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002732 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002733 for (; node; node = ebmb_next_dup(node)) {
2734 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002735 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002736 return order;
2737 }
2738
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002739 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002740 if (!sc)
2741 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002742 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002743 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002744 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002745 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002746 sc->order = order++;
2747 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002748 if (kinfo.sig != TLSEXT_signature_anonymous)
2749 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002750 if (wild)
2751 ebst_insert(&s->sni_w_ctx, &sc->name);
2752 else
2753 ebst_insert(&s->sni_ctx, &sc->name);
2754 }
2755 return order;
2756}
2757
yanbzhu488a4d22015-12-01 15:16:07 -05002758
2759/* The following code is used for loading multiple crt files into
2760 * SSL_CTX's based on CN/SAN
2761 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002762#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002763/* This is used to preload the certifcate, private key
2764 * and Cert Chain of a file passed in via the crt
2765 * argument
2766 *
2767 * This way, we do not have to read the file multiple times
2768 */
2769struct cert_key_and_chain {
2770 X509 *cert;
2771 EVP_PKEY *key;
2772 unsigned int num_chain_certs;
2773 /* This is an array of X509 pointers */
2774 X509 **chain_certs;
2775};
2776
yanbzhu08ce6ab2015-12-02 13:01:29 -05002777#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2778
2779struct key_combo_ctx {
2780 SSL_CTX *ctx;
2781 int order;
2782};
2783
2784/* Map used for processing multiple keypairs for a single purpose
2785 *
2786 * This maps CN/SNI name to certificate type
2787 */
2788struct sni_keytype {
2789 int keytypes; /* BITMASK for keytypes */
2790 struct ebmb_node name; /* node holding the servername value */
2791};
2792
2793
yanbzhu488a4d22015-12-01 15:16:07 -05002794/* Frees the contents of a cert_key_and_chain
2795 */
2796static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2797{
2798 int i;
2799
2800 if (!ckch)
2801 return;
2802
2803 /* Free the certificate and set pointer to NULL */
2804 if (ckch->cert)
2805 X509_free(ckch->cert);
2806 ckch->cert = NULL;
2807
2808 /* Free the key and set pointer to NULL */
2809 if (ckch->key)
2810 EVP_PKEY_free(ckch->key);
2811 ckch->key = NULL;
2812
2813 /* Free each certificate in the chain */
2814 for (i = 0; i < ckch->num_chain_certs; i++) {
2815 if (ckch->chain_certs[i])
2816 X509_free(ckch->chain_certs[i]);
2817 }
2818
2819 /* Free the chain obj itself and set to NULL */
2820 if (ckch->num_chain_certs > 0) {
2821 free(ckch->chain_certs);
2822 ckch->num_chain_certs = 0;
2823 ckch->chain_certs = NULL;
2824 }
2825
2826}
2827
2828/* checks if a key and cert exists in the ckch
2829 */
2830static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2831{
2832 return (ckch->cert != NULL && ckch->key != NULL);
2833}
2834
2835
2836/* Loads the contents of a crt file (path) into a cert_key_and_chain
2837 * This allows us to carry the contents of the file without having to
2838 * read the file multiple times.
2839 *
2840 * returns:
2841 * 0 on Success
2842 * 1 on SSL Failure
2843 * 2 on file not found
2844 */
2845static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2846{
2847
2848 BIO *in;
2849 X509 *ca = NULL;
2850 int ret = 1;
2851
2852 ssl_sock_free_cert_key_and_chain_contents(ckch);
2853
2854 in = BIO_new(BIO_s_file());
2855 if (in == NULL)
2856 goto end;
2857
2858 if (BIO_read_filename(in, path) <= 0)
2859 goto end;
2860
yanbzhu488a4d22015-12-01 15:16:07 -05002861 /* Read Private Key */
2862 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2863 if (ckch->key == NULL) {
2864 memprintf(err, "%sunable to load private key from file '%s'.\n",
2865 err && *err ? *err : "", path);
2866 goto end;
2867 }
2868
Willy Tarreaubb137a82016-04-06 19:02:38 +02002869 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002870 if (BIO_reset(in) == -1) {
2871 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2872 err && *err ? *err : "", path);
2873 goto end;
2874 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002875
2876 /* Read Certificate */
2877 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2878 if (ckch->cert == NULL) {
2879 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2880 err && *err ? *err : "", path);
2881 goto end;
2882 }
2883
yanbzhu488a4d22015-12-01 15:16:07 -05002884 /* Read Certificate Chain */
2885 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2886 /* Grow the chain certs */
2887 ckch->num_chain_certs++;
2888 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2889
2890 /* use - 1 here since we just incremented it above */
2891 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2892 }
2893 ret = ERR_get_error();
2894 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2895 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2896 err && *err ? *err : "", path);
2897 ret = 1;
2898 goto end;
2899 }
2900
2901 ret = 0;
2902
2903end:
2904
2905 ERR_clear_error();
2906 if (in)
2907 BIO_free(in);
2908
2909 /* Something went wrong in one of the reads */
2910 if (ret != 0)
2911 ssl_sock_free_cert_key_and_chain_contents(ckch);
2912
2913 return ret;
2914}
2915
2916/* Loads the info in ckch into ctx
2917 * Currently, this does not process any information about ocsp, dhparams or
2918 * sctl
2919 * Returns
2920 * 0 on success
2921 * 1 on failure
2922 */
2923static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2924{
2925 int i = 0;
2926
2927 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2928 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2929 err && *err ? *err : "", path);
2930 return 1;
2931 }
2932
2933 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2934 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2935 err && *err ? *err : "", path);
2936 return 1;
2937 }
2938
yanbzhu488a4d22015-12-01 15:16:07 -05002939 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2940 for (i = 0; i < ckch->num_chain_certs; i++) {
2941 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002942 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2943 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002944 return 1;
2945 }
2946 }
2947
2948 if (SSL_CTX_check_private_key(ctx) <= 0) {
2949 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2950 err && *err ? *err : "", path);
2951 return 1;
2952 }
2953
2954 return 0;
2955}
2956
yanbzhu08ce6ab2015-12-02 13:01:29 -05002957
2958static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2959{
2960 struct sni_keytype *s_kt = NULL;
2961 struct ebmb_node *node;
2962 int i;
2963
2964 for (i = 0; i < trash.size; i++) {
2965 if (!str[i])
2966 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002967 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002968 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002969 trash.area[i] = 0;
2970 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002971 if (!node) {
2972 /* CN not found in tree */
2973 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2974 /* Using memcpy here instead of strncpy.
2975 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2976 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2977 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002978 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002979 s_kt->keytypes = 0;
2980 ebst_insert(sni_keytypes, &s_kt->name);
2981 } else {
2982 /* CN found in tree */
2983 s_kt = container_of(node, struct sni_keytype, name);
2984 }
2985
2986 /* Mark that this CN has the keytype of key_index via keytypes mask */
2987 s_kt->keytypes |= 1<<key_index;
2988
2989}
2990
2991
2992/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2993 * If any are found, group these files into a set of SSL_CTX*
2994 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2995 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08002996 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05002997 *
2998 * Returns
2999 * 0 on success
3000 * 1 on failure
3001 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003002static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3003 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003004{
3005 char fp[MAXPATHLEN+1] = {0};
3006 int n = 0;
3007 int i = 0;
3008 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3009 struct eb_root sni_keytypes_map = { {0} };
3010 struct ebmb_node *node;
3011 struct ebmb_node *next;
3012 /* Array of SSL_CTX pointers corresponding to each possible combo
3013 * of keytypes
3014 */
3015 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3016 int rv = 0;
3017 X509_NAME *xname = NULL;
3018 char *str = NULL;
3019#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3020 STACK_OF(GENERAL_NAME) *names = NULL;
3021#endif
3022
3023 /* Load all possible certs and keys */
3024 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3025 struct stat buf;
3026
3027 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3028 if (stat(fp, &buf) == 0) {
3029 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3030 rv = 1;
3031 goto end;
3032 }
3033 }
3034 }
3035
3036 /* Process each ckch and update keytypes for each CN/SAN
3037 * for example, if CN/SAN www.a.com is associated with
3038 * certs with keytype 0 and 2, then at the end of the loop,
3039 * www.a.com will have:
3040 * keyindex = 0 | 1 | 4 = 5
3041 */
3042 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3043
3044 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3045 continue;
3046
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003047 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003048 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003049 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3050 } else {
3051 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3052 * so the line that contains logic is marked via comments
3053 */
3054 xname = X509_get_subject_name(certs_and_keys[n].cert);
3055 i = -1;
3056 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3057 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003058 ASN1_STRING *value;
3059 value = X509_NAME_ENTRY_get_data(entry);
3060 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003061 /* Important line is here */
3062 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003063
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003064 OPENSSL_free(str);
3065 str = NULL;
3066 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003067 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003068
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003069 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003070#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003071 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3072 if (names) {
3073 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3074 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003075
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003076 if (name->type == GEN_DNS) {
3077 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3078 /* Important line is here */
3079 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003081 OPENSSL_free(str);
3082 str = NULL;
3083 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003084 }
3085 }
3086 }
3087 }
3088#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3089 }
3090
3091 /* If no files found, return error */
3092 if (eb_is_empty(&sni_keytypes_map)) {
3093 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3094 err && *err ? *err : "", path);
3095 rv = 1;
3096 goto end;
3097 }
3098
3099 /* We now have a map of CN/SAN to keytypes that are loaded in
3100 * Iterate through the map to create the SSL_CTX's (if needed)
3101 * and add each CTX to the SNI tree
3102 *
3103 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003104 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003105 * combination is denoted by the key in the map. Each key
3106 * has a value between 1 and 2^n - 1. Conveniently, the array
3107 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3108 * entry in the array to correspond to the unique combo (key)
3109 * associated with i. This unique key combo (i) will be associated
3110 * with combos[i-1]
3111 */
3112
3113 node = ebmb_first(&sni_keytypes_map);
3114 while (node) {
3115 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003116 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003117 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003118
3119 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3120 i = container_of(node, struct sni_keytype, name)->keytypes;
3121 cur_ctx = key_combos[i-1].ctx;
3122
3123 if (cur_ctx == NULL) {
3124 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003125 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003126 if (cur_ctx == NULL) {
3127 memprintf(err, "%sunable to allocate SSL context.\n",
3128 err && *err ? *err : "");
3129 rv = 1;
3130 goto end;
3131 }
3132
yanbzhube2774d2015-12-10 15:07:30 -05003133 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003134 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3135 if (i & (1<<n)) {
3136 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003137 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3138 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003139 SSL_CTX_free(cur_ctx);
3140 rv = 1;
3141 goto end;
3142 }
yanbzhube2774d2015-12-10 15:07:30 -05003143
3144#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3145 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003146 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003147 if (err)
3148 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
Bertrand Jacquin5424ee02016-11-13 16:37:14 +00003149 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003150 SSL_CTX_free(cur_ctx);
3151 rv = 1;
3152 goto end;
3153 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003154#elif (defined OPENSSL_IS_BORINGSSL)
3155 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003156#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003157 }
3158 }
3159
3160 /* Load DH params into the ctx to support DHE keys */
3161#ifndef OPENSSL_NO_DH
3162 if (ssl_dh_ptr_index >= 0)
3163 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3164
3165 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3166 if (rv < 0) {
3167 if (err)
3168 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3169 *err ? *err : "", path);
3170 rv = 1;
3171 goto end;
3172 }
3173#endif
3174
3175 /* Update key_combos */
3176 key_combos[i-1].ctx = cur_ctx;
3177 }
3178
3179 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003180 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003181 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003182 node = ebmb_next(node);
3183 }
3184
3185
3186 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3187 if (!bind_conf->default_ctx) {
3188 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3189 if (key_combos[i].ctx) {
3190 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003191 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003192 break;
3193 }
3194 }
3195 }
3196
3197end:
3198
3199 if (names)
3200 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3201
3202 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3203 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3204
3205 node = ebmb_first(&sni_keytypes_map);
3206 while (node) {
3207 next = ebmb_next(node);
3208 ebmb_delete(node);
3209 node = next;
3210 }
3211
3212 return rv;
3213}
3214#else
3215/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003216static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3217 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003218{
3219 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3220 err && *err ? *err : "", path, strerror(errno));
3221 return 1;
3222}
3223
yanbzhu488a4d22015-12-01 15:16:07 -05003224#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3225
Emeric Brunfc0421f2012-09-07 17:30:07 +02003226/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3227 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3228 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003229static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3230 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003231{
3232 BIO *in;
3233 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003234 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235 int ret = -1;
3236 int order = 0;
3237 X509_NAME *xname;
3238 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003239 pem_password_cb *passwd_cb;
3240 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003241 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003242 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003243
Emeric Brunfc0421f2012-09-07 17:30:07 +02003244#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3245 STACK_OF(GENERAL_NAME) *names;
3246#endif
3247
3248 in = BIO_new(BIO_s_file());
3249 if (in == NULL)
3250 goto end;
3251
3252 if (BIO_read_filename(in, file) <= 0)
3253 goto end;
3254
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003255
3256 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3257 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3258
3259 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260 if (x == NULL)
3261 goto end;
3262
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003263 pkey = X509_get_pubkey(x);
3264 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003265 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003266 switch(EVP_PKEY_base_id(pkey)) {
3267 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003268 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003269 break;
3270 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003271 kinfo.sig = TLSEXT_signature_ecdsa;
3272 break;
3273 case EVP_PKEY_DSA:
3274 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003275 break;
3276 }
3277 EVP_PKEY_free(pkey);
3278 }
3279
Emeric Brun50bcecc2013-04-22 13:05:23 +02003280 if (fcount) {
3281 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003282 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003283 }
3284 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003285#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003286 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3287 if (names) {
3288 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3289 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3290 if (name->type == GEN_DNS) {
3291 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003292 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003293 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003294 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003295 }
3296 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003297 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003298 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003299#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003300 xname = X509_get_subject_name(x);
3301 i = -1;
3302 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3303 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003304 ASN1_STRING *value;
3305
3306 value = X509_NAME_ENTRY_get_data(entry);
3307 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003308 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003309 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003310 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003311 }
3312 }
3313
3314 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3315 if (!SSL_CTX_use_certificate(ctx, x))
3316 goto end;
3317
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003318#ifdef SSL_CTX_clear_extra_chain_certs
3319 SSL_CTX_clear_extra_chain_certs(ctx);
3320#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003321 if (ctx->extra_certs != NULL) {
3322 sk_X509_pop_free(ctx->extra_certs, X509_free);
3323 ctx->extra_certs = NULL;
3324 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003325#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003326
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003327 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003328 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3329 X509_free(ca);
3330 goto end;
3331 }
3332 }
3333
3334 err = ERR_get_error();
3335 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3336 /* we successfully reached the last cert in the file */
3337 ret = 1;
3338 }
3339 ERR_clear_error();
3340
3341end:
3342 if (x)
3343 X509_free(x);
3344
3345 if (in)
3346 BIO_free(in);
3347
3348 return ret;
3349}
3350
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003351static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3352 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003353{
3354 int ret;
3355 SSL_CTX *ctx;
3356
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003357 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003358 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003359 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3360 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003361 return 1;
3362 }
3363
3364 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003365 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3366 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003367 SSL_CTX_free(ctx);
3368 return 1;
3369 }
3370
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003371 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003372 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003373 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3374 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003375 if (ret < 0) /* serious error, must do that ourselves */
3376 SSL_CTX_free(ctx);
3377 return 1;
3378 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003379
3380 if (SSL_CTX_check_private_key(ctx) <= 0) {
3381 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3382 err && *err ? *err : "", path);
3383 return 1;
3384 }
3385
Emeric Brunfc0421f2012-09-07 17:30:07 +02003386 /* we must not free the SSL_CTX anymore below, since it's already in
3387 * the tree, so it will be discovered and cleaned in time.
3388 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003389#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003390 /* store a NULL pointer to indicate we have not yet loaded
3391 a custom DH param file */
3392 if (ssl_dh_ptr_index >= 0) {
3393 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3394 }
3395
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003396 ret = ssl_sock_load_dh_params(ctx, path);
3397 if (ret < 0) {
3398 if (err)
3399 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3400 *err ? *err : "", path);
3401 return 1;
3402 }
3403#endif
3404
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003405#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003406 ret = ssl_sock_load_ocsp(ctx, path);
3407 if (ret < 0) {
3408 if (err)
3409 memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
3410 *err ? *err : "", path);
3411 return 1;
3412 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003413#elif (defined OPENSSL_IS_BORINGSSL)
3414 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003415#endif
3416
Daniel Jakots54ffb912015-11-06 20:02:41 +01003417#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003418 if (sctl_ex_index >= 0) {
3419 ret = ssl_sock_load_sctl(ctx, path);
3420 if (ret < 0) {
3421 if (err)
3422 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3423 *err ? *err : "", path);
3424 return 1;
3425 }
3426 }
3427#endif
3428
Emeric Brunfc0421f2012-09-07 17:30:07 +02003429#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003430 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003431 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3432 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003433 return 1;
3434 }
3435#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003436 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003437 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003438 bind_conf->default_ssl_conf = ssl_conf;
3439 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003440
3441 return 0;
3442}
3443
Willy Tarreau03209342016-12-22 17:08:28 +01003444int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003445{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003446 struct dirent **de_list;
3447 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003448 DIR *dir;
3449 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003450 char *end;
3451 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003452 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003453#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3454 int is_bundle;
3455 int j;
3456#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003457
yanbzhu08ce6ab2015-12-02 13:01:29 -05003458 if (stat(path, &buf) == 0) {
3459 dir = opendir(path);
3460 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003461 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003462
yanbzhu08ce6ab2015-12-02 13:01:29 -05003463 /* strip trailing slashes, including first one */
3464 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3465 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003466
yanbzhu08ce6ab2015-12-02 13:01:29 -05003467 n = scandir(path, &de_list, 0, alphasort);
3468 if (n < 0) {
3469 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3470 err && *err ? *err : "", path, strerror(errno));
3471 cfgerr++;
3472 }
3473 else {
3474 for (i = 0; i < n; i++) {
3475 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003476
yanbzhu08ce6ab2015-12-02 13:01:29 -05003477 end = strrchr(de->d_name, '.');
3478 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3479 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003480
yanbzhu08ce6ab2015-12-02 13:01:29 -05003481 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3482 if (stat(fp, &buf) != 0) {
3483 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3484 err && *err ? *err : "", fp, strerror(errno));
3485 cfgerr++;
3486 goto ignore_entry;
3487 }
3488 if (!S_ISREG(buf.st_mode))
3489 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003490
3491#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3492 is_bundle = 0;
3493 /* Check if current entry in directory is part of a multi-cert bundle */
3494
3495 if (end) {
3496 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3497 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3498 is_bundle = 1;
3499 break;
3500 }
3501 }
3502
3503 if (is_bundle) {
3504 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3505 int dp_len;
3506
3507 dp_len = end - de->d_name;
3508 snprintf(dp, dp_len + 1, "%s", de->d_name);
3509
3510 /* increment i and free de until we get to a non-bundle cert
3511 * Note here that we look at de_list[i + 1] before freeing de
3512 * this is important since ignore_entry will free de
3513 */
3514 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3515 free(de);
3516 i++;
3517 de = de_list[i];
3518 }
3519
3520 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003521 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003522
3523 /* Successfully processed the bundle */
3524 goto ignore_entry;
3525 }
3526 }
3527
3528#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003529 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003530ignore_entry:
3531 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003532 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003533 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003534 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003535 closedir(dir);
3536 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003537 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003538
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003539 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003540
Emeric Brunfc0421f2012-09-07 17:30:07 +02003541 return cfgerr;
3542}
3543
Thierry Fournier383085f2013-01-24 14:15:43 +01003544/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3545 * done once. Zero is returned if the operation fails. No error is returned
3546 * if the random is said as not implemented, because we expect that openssl
3547 * will use another method once needed.
3548 */
3549static int ssl_initialize_random()
3550{
3551 unsigned char random;
3552 static int random_initialized = 0;
3553
3554 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3555 random_initialized = 1;
3556
3557 return random_initialized;
3558}
3559
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003560/* release ssl bind conf */
3561void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003562{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003563 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003564#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003565 free(conf->npn_str);
3566 conf->npn_str = NULL;
3567#endif
3568#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3569 free(conf->alpn_str);
3570 conf->alpn_str = NULL;
3571#endif
3572 free(conf->ca_file);
3573 conf->ca_file = NULL;
3574 free(conf->crl_file);
3575 conf->crl_file = NULL;
3576 free(conf->ciphers);
3577 conf->ciphers = NULL;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003578#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
3579 free(conf->ciphersuites);
3580 conf->ciphersuites = NULL;
3581#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003582 free(conf->curves);
3583 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003584 free(conf->ecdhe);
3585 conf->ecdhe = NULL;
3586 }
3587}
3588
3589int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3590{
3591 char thisline[CRT_LINESIZE];
3592 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003593 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003594 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003595 int linenum = 0;
3596 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003597
Willy Tarreauad1731d2013-04-02 17:35:58 +02003598 if ((f = fopen(file, "r")) == NULL) {
3599 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003600 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003601 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003602
3603 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003604 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003606 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003607 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003608 char *crt_path;
3609 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003610
3611 linenum++;
3612 end = line + strlen(line);
3613 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3614 /* Check if we reached the limit and the last char is not \n.
3615 * Watch out for the last line without the terminating '\n'!
3616 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003617 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3618 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003619 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003620 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003621 }
3622
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003623 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003624 newarg = 1;
3625 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003626 if (*line == '#' || *line == '\n' || *line == '\r') {
3627 /* end of string, end of loop */
3628 *line = 0;
3629 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003630 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003631 newarg = 1;
3632 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003633 } else if (*line == '[') {
3634 if (ssl_b) {
3635 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3636 cfgerr = 1;
3637 break;
3638 }
3639 if (!arg) {
3640 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3641 cfgerr = 1;
3642 break;
3643 }
3644 ssl_b = arg;
3645 newarg = 1;
3646 *line = 0;
3647 } else if (*line == ']') {
3648 if (ssl_e) {
3649 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003650 cfgerr = 1;
3651 break;
3652 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003653 if (!ssl_b) {
3654 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3655 cfgerr = 1;
3656 break;
3657 }
3658 ssl_e = arg;
3659 newarg = 1;
3660 *line = 0;
3661 } else if (newarg) {
3662 if (arg == MAX_CRT_ARGS) {
3663 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3664 cfgerr = 1;
3665 break;
3666 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003667 newarg = 0;
3668 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003669 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003670 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003672 if (cfgerr)
3673 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003674 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003675
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003676 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003677 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003678 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003679
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003680 crt_path = args[0];
3681 if (*crt_path != '/' && global_ssl.crt_base) {
3682 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3683 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3684 crt_path, linenum, file);
3685 cfgerr = 1;
3686 break;
3687 }
3688 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3689 crt_path = path;
3690 }
3691
3692 ssl_conf = calloc(1, sizeof *ssl_conf);
3693 cur_arg = ssl_b ? ssl_b : 1;
3694 while (cur_arg < ssl_e) {
3695 newarg = 0;
3696 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3697 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3698 newarg = 1;
3699 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3700 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3701 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3702 args[cur_arg], linenum, file);
3703 cfgerr = 1;
3704 }
3705 cur_arg += 1 + ssl_bind_kws[i].skip;
3706 break;
3707 }
3708 }
3709 if (!cfgerr && !newarg) {
3710 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3711 args[cur_arg], linenum, file);
3712 cfgerr = 1;
3713 break;
3714 }
3715 }
3716 if (cfgerr) {
3717 ssl_sock_free_ssl_conf(ssl_conf);
3718 free(ssl_conf);
3719 ssl_conf = NULL;
3720 break;
3721 }
3722
3723 if (stat(crt_path, &buf) == 0) {
3724 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3725 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003726 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003727 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3728 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003729 }
3730
Willy Tarreauad1731d2013-04-02 17:35:58 +02003731 if (cfgerr) {
3732 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003733 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003734 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003735 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003736 fclose(f);
3737 return cfgerr;
3738}
3739
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003740/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003741static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003742ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003743{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003744 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003745 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003746 SSL_OP_ALL | /* all known workarounds for bugs */
3747 SSL_OP_NO_SSLv2 |
3748 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003749 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003750 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003751 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003752 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003753 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003754 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003755 SSL_MODE_ENABLE_PARTIAL_WRITE |
3756 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003757 SSL_MODE_RELEASE_BUFFERS |
3758 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003759 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003760 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003761 int flags = MC_SSL_O_ALL;
3762 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003763
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003764 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003765 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003766
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003767 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003768 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3769 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3770 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003771 else
3772 flags = conf_ssl_methods->flags;
3773
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003774 min = conf_ssl_methods->min;
3775 max = conf_ssl_methods->max;
3776 /* start with TLSv10 to remove SSLv3 per default */
3777 if (!min && (!max || max >= CONF_TLSV10))
3778 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003779 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003780 if (min)
3781 flags |= (methodVersions[min].flag - 1);
3782 if (max)
3783 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003784 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003785 min = max = CONF_TLSV_NONE;
3786 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003787 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003788 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003789 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003790 if (min) {
3791 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003792 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3793 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3794 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3795 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003796 hole = 0;
3797 }
3798 max = i;
3799 }
3800 else {
3801 min = max = i;
3802 }
3803 }
3804 else {
3805 if (min)
3806 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003807 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003808 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003809 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3810 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003811 cfgerr += 1;
3812 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003813 /* save real min/max in bind_conf */
3814 conf_ssl_methods->min = min;
3815 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003816
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003817#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003818 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003819 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003820 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003821 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003822 else
3823 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3824 if (flags & methodVersions[i].flag)
3825 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003826#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003827 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003828 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3829 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003830#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003831
3832 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3833 options |= SSL_OP_NO_TICKET;
3834 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3835 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3836 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003837
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003838#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003839 if (global_ssl.async)
3840 mode |= SSL_MODE_ASYNC;
3841#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003842 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003843 if (global_ssl.life_time)
3844 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003845
3846#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3847#ifdef OPENSSL_IS_BORINGSSL
3848 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3849 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003850#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3851 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3852 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003853#else
3854 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003855#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003856 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003857#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003858 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003859}
3860
William Lallemand4f45bb92017-10-30 20:08:51 +01003861
3862static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3863{
3864 if (first == block) {
3865 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3866 if (first->len > 0)
3867 sh_ssl_sess_tree_delete(sh_ssl_sess);
3868 }
3869}
3870
3871/* return first block from sh_ssl_sess */
3872static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3873{
3874 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3875
3876}
3877
3878/* store a session into the cache
3879 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3880 * data: asn1 encoded session
3881 * data_len: asn1 encoded session length
3882 * Returns 1 id session was stored (else 0)
3883 */
3884static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3885{
3886 struct shared_block *first;
3887 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3888
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003889 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01003890 if (!first) {
3891 /* Could not retrieve enough free blocks to store that session */
3892 return 0;
3893 }
3894
3895 /* STORE the key in the first elem */
3896 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3897 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3898 first->len = sizeof(struct sh_ssl_sess_hdr);
3899
3900 /* it returns the already existing node
3901 or current node if none, never returns null */
3902 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3903 if (oldsh_ssl_sess != sh_ssl_sess) {
3904 /* NOTE: Row couldn't be in use because we lock read & write function */
3905 /* release the reserved row */
3906 shctx_row_dec_hot(ssl_shctx, first);
3907 /* replace the previous session already in the tree */
3908 sh_ssl_sess = oldsh_ssl_sess;
3909 /* ignore the previous session data, only use the header */
3910 first = sh_ssl_sess_first_block(sh_ssl_sess);
3911 shctx_row_inc_hot(ssl_shctx, first);
3912 first->len = sizeof(struct sh_ssl_sess_hdr);
3913 }
3914
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02003915 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01003916 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003917 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003918 }
3919
3920 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003921
3922 return 1;
3923}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003924
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003925/* SSL callback used when a new session is created while connecting to a server */
3926static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3927{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003928 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003929 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003930
Willy Tarreau07d94e42018-09-20 10:57:52 +02003931 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003932
Olivier Houcharde6060c52017-11-16 17:42:52 +01003933 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3934 int len;
3935 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003936
Olivier Houcharde6060c52017-11-16 17:42:52 +01003937 len = i2d_SSL_SESSION(sess, NULL);
3938 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3939 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3940 } else {
3941 free(s->ssl_ctx.reused_sess[tid].ptr);
3942 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3943 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3944 }
3945 if (s->ssl_ctx.reused_sess[tid].ptr) {
3946 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3947 &ptr);
3948 }
3949 } else {
3950 free(s->ssl_ctx.reused_sess[tid].ptr);
3951 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3952 }
3953
3954 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003955}
3956
Olivier Houcharde6060c52017-11-16 17:42:52 +01003957
William Lallemanded0b5ad2017-10-30 19:36:36 +01003958/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003959int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003960{
3961 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3962 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3963 unsigned char *p;
3964 int data_len;
3965 unsigned int sid_length, sid_ctx_length;
3966 const unsigned char *sid_data;
3967 const unsigned char *sid_ctx_data;
3968
3969 /* Session id is already stored in to key and session id is known
3970 * so we dont store it to keep size.
3971 */
3972
3973 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3974 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3975 SSL_SESSION_set1_id(sess, sid_data, 0);
3976 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3977
3978 /* check if buffer is large enough for the ASN1 encoded session */
3979 data_len = i2d_SSL_SESSION(sess, NULL);
3980 if (data_len > SHSESS_MAX_DATA_LEN)
3981 goto err;
3982
3983 p = encsess;
3984
3985 /* process ASN1 session encoding before the lock */
3986 i2d_SSL_SESSION(sess, &p);
3987
3988 memcpy(encid, sid_data, sid_length);
3989 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3990 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3991
William Lallemanda3c77cf2017-10-30 23:44:40 +01003992 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003993 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003994 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003995 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003996err:
3997 /* reset original length values */
3998 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3999 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4000
4001 return 0; /* do not increment session reference count */
4002}
4003
4004/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004005SSL_SESSION *sh_ssl_sess_get_cb(SSL *ssl, __OPENSSL_110_CONST__ unsigned char *key, int key_len, int *do_copy)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004006{
William Lallemand4f45bb92017-10-30 20:08:51 +01004007 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004008 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4009 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004010 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004011 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004012
4013 global.shctx_lookups++;
4014
4015 /* allow the session to be freed automatically by openssl */
4016 *do_copy = 0;
4017
4018 /* tree key is zeros padded sessionid */
4019 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4020 memcpy(tmpkey, key, key_len);
4021 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4022 key = tmpkey;
4023 }
4024
4025 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004026 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004027
4028 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004029 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4030 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004031 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004032 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004033 global.shctx_misses++;
4034 return NULL;
4035 }
4036
William Lallemand4f45bb92017-10-30 20:08:51 +01004037 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4038 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004039
William Lallemand4f45bb92017-10-30 20:08:51 +01004040 shctx_row_data_get(ssl_shctx, first, data, sizeof(struct sh_ssl_sess_hdr), first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004041
William Lallemanda3c77cf2017-10-30 23:44:40 +01004042 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004043
4044 /* decode ASN1 session */
4045 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004046 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004047 /* Reset session id and session id contenxt */
4048 if (sess) {
4049 SSL_SESSION_set1_id(sess, key, key_len);
4050 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4051 }
4052
4053 return sess;
4054}
4055
William Lallemand4f45bb92017-10-30 20:08:51 +01004056
William Lallemanded0b5ad2017-10-30 19:36:36 +01004057/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004058void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004059{
William Lallemand4f45bb92017-10-30 20:08:51 +01004060 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004061 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4062 unsigned int sid_length;
4063 const unsigned char *sid_data;
4064 (void)ctx;
4065
4066 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4067 /* tree key is zeros padded sessionid */
4068 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4069 memcpy(tmpkey, sid_data, sid_length);
4070 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4071 sid_data = tmpkey;
4072 }
4073
William Lallemanda3c77cf2017-10-30 23:44:40 +01004074 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004075
4076 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004077 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4078 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004079 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004080 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004081 }
4082
4083 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004084 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004085}
4086
4087/* Set session cache mode to server and disable openssl internal cache.
4088 * Set shared cache callbacks on an ssl context.
4089 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004090void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004091{
4092 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4093
4094 if (!ssl_shctx) {
4095 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4096 return;
4097 }
4098
4099 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4100 SSL_SESS_CACHE_NO_INTERNAL |
4101 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4102
4103 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004104 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4105 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4106 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004107}
4108
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004109int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4110{
4111 struct proxy *curproxy = bind_conf->frontend;
4112 int cfgerr = 0;
4113 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004114 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004115 const char *conf_ciphers;
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004116#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4117 const char *conf_ciphersuites;
4118#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004119 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004120
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004121 if (ssl_conf) {
4122 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4123 int i, min, max;
4124 int flags = MC_SSL_O_ALL;
4125
4126 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004127 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4128 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004129 if (min)
4130 flags |= (methodVersions[min].flag - 1);
4131 if (max)
4132 flags |= ~((methodVersions[max].flag << 1) - 1);
4133 min = max = CONF_TLSV_NONE;
4134 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4135 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4136 if (min)
4137 max = i;
4138 else
4139 min = max = i;
4140 }
4141 /* save real min/max */
4142 conf_ssl_methods->min = min;
4143 conf_ssl_methods->max = max;
4144 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004145 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4146 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004147 cfgerr += 1;
4148 }
4149 }
4150
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004151 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004152 case SSL_SOCK_VERIFY_NONE:
4153 verify = SSL_VERIFY_NONE;
4154 break;
4155 case SSL_SOCK_VERIFY_OPTIONAL:
4156 verify = SSL_VERIFY_PEER;
4157 break;
4158 case SSL_SOCK_VERIFY_REQUIRED:
4159 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4160 break;
4161 }
4162 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4163 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004164 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4165 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4166 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004167 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004168 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004169 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4170 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004171 cfgerr++;
4172 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004173 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4174 /* set CA names for client cert request, function returns void */
4175 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4176 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004177 }
Emeric Brun850efd52014-01-29 12:24:34 +01004178 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004179 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4180 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004181 cfgerr++;
4182 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004183#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004184 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004185 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4186
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004187 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004188 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4189 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004190 cfgerr++;
4191 }
Emeric Brun561e5742012-10-02 15:20:55 +02004192 else {
4193 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4194 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004195 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004196#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004197 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004198 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004199#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004200 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004201 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004202 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4203 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004204 cfgerr++;
4205 }
4206 }
4207#endif
4208
William Lallemand4f45bb92017-10-30 20:08:51 +01004209 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004210 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4211 if (conf_ciphers &&
4212 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004213 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4214 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004215 cfgerr++;
4216 }
4217
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004218#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4219 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4220 if (conf_ciphersuites &&
4221 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4222 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4223 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4224 cfgerr++;
4225 }
4226#endif
4227
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004228#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004229 /* If tune.ssl.default-dh-param has not been set,
4230 neither has ssl-default-dh-file and no static DH
4231 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004232 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004233 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004234 (ssl_dh_ptr_index == -1 ||
4235 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004236 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4237 const SSL_CIPHER * cipher = NULL;
4238 char cipher_description[128];
4239 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4240 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4241 which is not ephemeral DH. */
4242 const char dhe_description[] = " Kx=DH ";
4243 const char dhe_export_description[] = " Kx=DH(";
4244 int idx = 0;
4245 int dhe_found = 0;
4246 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004247
Remi Gacogne23d5d372014-10-10 17:04:26 +02004248 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004249
Remi Gacogne23d5d372014-10-10 17:04:26 +02004250 if (ssl) {
4251 ciphers = SSL_get_ciphers(ssl);
4252
4253 if (ciphers) {
4254 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4255 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4256 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4257 if (strstr(cipher_description, dhe_description) != NULL ||
4258 strstr(cipher_description, dhe_export_description) != NULL) {
4259 dhe_found = 1;
4260 break;
4261 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004262 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004263 }
4264 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004265 SSL_free(ssl);
4266 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004267 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004268
Lukas Tribus90132722014-08-18 00:56:33 +02004269 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004270 ha_warning("Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear.\n");
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004271 }
4272
Willy Tarreauef934602016-12-22 23:12:01 +01004273 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004274 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004275
Willy Tarreauef934602016-12-22 23:12:01 +01004276 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004277 if (local_dh_1024 == NULL) {
4278 local_dh_1024 = ssl_get_dh_1024();
4279 }
Willy Tarreauef934602016-12-22 23:12:01 +01004280 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004281 if (local_dh_2048 == NULL) {
4282 local_dh_2048 = ssl_get_dh_2048();
4283 }
Willy Tarreauef934602016-12-22 23:12:01 +01004284 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004285 if (local_dh_4096 == NULL) {
4286 local_dh_4096 = ssl_get_dh_4096();
4287 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004288 }
4289 }
4290 }
4291#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004292
Emeric Brunfc0421f2012-09-07 17:30:07 +02004293 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004294#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004295 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004296#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004297
Bernard Spil13c53f82018-02-15 13:34:58 +01004298#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004299 ssl_conf_cur = NULL;
4300 if (ssl_conf && ssl_conf->npn_str)
4301 ssl_conf_cur = ssl_conf;
4302 else if (bind_conf->ssl_conf.npn_str)
4303 ssl_conf_cur = &bind_conf->ssl_conf;
4304 if (ssl_conf_cur)
4305 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004306#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004307#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004308 ssl_conf_cur = NULL;
4309 if (ssl_conf && ssl_conf->alpn_str)
4310 ssl_conf_cur = ssl_conf;
4311 else if (bind_conf->ssl_conf.alpn_str)
4312 ssl_conf_cur = &bind_conf->ssl_conf;
4313 if (ssl_conf_cur)
4314 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004315#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004316#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4317 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4318 if (conf_curves) {
4319 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004320 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4321 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004322 cfgerr++;
4323 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004324#if defined(SSL_CTX_set_ecdh_auto)
4325 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4326#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004327 }
4328#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004329#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004330 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004331 int i;
4332 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004333#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004334 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004335 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4336 NULL);
4337
4338 if (ecdhe == NULL) {
4339 SSL_CTX_set_dh_auto(ctx, 1);
4340 return cfgerr;
4341 }
4342#else
4343 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4344 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4345 ECDHE_DEFAULT_CURVE);
4346#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004347
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004348 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004349 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004350 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4351 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004352 cfgerr++;
4353 }
4354 else {
4355 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4356 EC_KEY_free(ecdh);
4357 }
4358 }
4359#endif
4360
Emeric Brunfc0421f2012-09-07 17:30:07 +02004361 return cfgerr;
4362}
4363
Evan Broderbe554312013-06-27 00:05:25 -07004364static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4365{
4366 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4367 size_t prefixlen, suffixlen;
4368
4369 /* Trivial case */
4370 if (strcmp(pattern, hostname) == 0)
4371 return 1;
4372
Evan Broderbe554312013-06-27 00:05:25 -07004373 /* The rest of this logic is based on RFC 6125, section 6.4.3
4374 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4375
Emeric Bruna848dae2013-10-08 11:27:28 +02004376 pattern_wildcard = NULL;
4377 pattern_left_label_end = pattern;
4378 while (*pattern_left_label_end != '.') {
4379 switch (*pattern_left_label_end) {
4380 case 0:
4381 /* End of label not found */
4382 return 0;
4383 case '*':
4384 /* If there is more than one wildcards */
4385 if (pattern_wildcard)
4386 return 0;
4387 pattern_wildcard = pattern_left_label_end;
4388 break;
4389 }
4390 pattern_left_label_end++;
4391 }
4392
4393 /* If it's not trivial and there is no wildcard, it can't
4394 * match */
4395 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004396 return 0;
4397
4398 /* Make sure all labels match except the leftmost */
4399 hostname_left_label_end = strchr(hostname, '.');
4400 if (!hostname_left_label_end
4401 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4402 return 0;
4403
4404 /* Make sure the leftmost label of the hostname is long enough
4405 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004406 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004407 return 0;
4408
4409 /* Finally compare the string on either side of the
4410 * wildcard */
4411 prefixlen = pattern_wildcard - pattern;
4412 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004413 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4414 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004415 return 0;
4416
4417 return 1;
4418}
4419
4420static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4421{
4422 SSL *ssl;
4423 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004424 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004425 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004426
4427 int depth;
4428 X509 *cert;
4429 STACK_OF(GENERAL_NAME) *alt_names;
4430 int i;
4431 X509_NAME *cert_subject;
4432 char *str;
4433
4434 if (ok == 0)
4435 return ok;
4436
4437 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004438 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004439
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004440 /* We're checking if the provided hostnames match the desired one. The
4441 * desired hostname comes from the SNI we presented if any, or if not
4442 * provided then it may have been explicitly stated using a "verifyhost"
4443 * directive. If neither is set, we don't care about the name so the
4444 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004445 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004446 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004447 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004448 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004449 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004450 if (!servername)
4451 return ok;
4452 }
Evan Broderbe554312013-06-27 00:05:25 -07004453
4454 /* We only need to verify the CN on the actual server cert,
4455 * not the indirect CAs */
4456 depth = X509_STORE_CTX_get_error_depth(ctx);
4457 if (depth != 0)
4458 return ok;
4459
4460 /* At this point, the cert is *not* OK unless we can find a
4461 * hostname match */
4462 ok = 0;
4463
4464 cert = X509_STORE_CTX_get_current_cert(ctx);
4465 /* It seems like this might happen if verify peer isn't set */
4466 if (!cert)
4467 return ok;
4468
4469 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4470 if (alt_names) {
4471 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4472 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4473 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004474#if OPENSSL_VERSION_NUMBER < 0x00907000L
4475 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4476#else
Evan Broderbe554312013-06-27 00:05:25 -07004477 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004478#endif
Evan Broderbe554312013-06-27 00:05:25 -07004479 ok = ssl_sock_srv_hostcheck(str, servername);
4480 OPENSSL_free(str);
4481 }
4482 }
4483 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004484 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004485 }
4486
4487 cert_subject = X509_get_subject_name(cert);
4488 i = -1;
4489 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4490 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004491 ASN1_STRING *value;
4492 value = X509_NAME_ENTRY_get_data(entry);
4493 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004494 ok = ssl_sock_srv_hostcheck(str, servername);
4495 OPENSSL_free(str);
4496 }
4497 }
4498
Willy Tarreau71d058c2017-07-26 20:09:56 +02004499 /* report the mismatch and indicate if SNI was used or not */
4500 if (!ok && !conn->err_code)
4501 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004502 return ok;
4503}
4504
Emeric Brun94324a42012-10-11 14:00:19 +02004505/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004506int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004507{
Willy Tarreau03209342016-12-22 17:08:28 +01004508 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004509 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004510 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004511 SSL_OP_ALL | /* all known workarounds for bugs */
4512 SSL_OP_NO_SSLv2 |
4513 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004514 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004515 SSL_MODE_ENABLE_PARTIAL_WRITE |
4516 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004517 SSL_MODE_RELEASE_BUFFERS |
4518 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004519 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004520 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004521 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004522 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004523 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004524
Thierry Fournier383085f2013-01-24 14:15:43 +01004525 /* Make sure openssl opens /dev/urandom before the chroot */
4526 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004527 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004528 cfgerr++;
4529 }
4530
Willy Tarreaufce03112015-01-15 21:32:40 +01004531 /* Automatic memory computations need to know we use SSL there */
4532 global.ssl_used_backend = 1;
4533
4534 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004535 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004536 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004537 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4538 curproxy->id, srv->id,
4539 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004540 cfgerr++;
4541 return cfgerr;
4542 }
4543 }
Emeric Brun94324a42012-10-11 14:00:19 +02004544 if (srv->use_ssl)
4545 srv->xprt = &ssl_sock;
4546 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004547 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004548
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004549 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004550 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004551 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4552 proxy_type_str(curproxy), curproxy->id,
4553 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004554 cfgerr++;
4555 return cfgerr;
4556 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004557
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004558 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004559 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4560 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4561 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004562 else
4563 flags = conf_ssl_methods->flags;
4564
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004565 /* Real min and max should be determinate with configuration and openssl's capabilities */
4566 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004567 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004568 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004569 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004570
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004571 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004572 min = max = CONF_TLSV_NONE;
4573 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004574 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004575 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004576 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004577 if (min) {
4578 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004579 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4580 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4581 proxy_type_str(curproxy), curproxy->id, srv->id,
4582 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004583 hole = 0;
4584 }
4585 max = i;
4586 }
4587 else {
4588 min = max = i;
4589 }
4590 }
4591 else {
4592 if (min)
4593 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004594 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004595 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004596 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4597 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004598 cfgerr += 1;
4599 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004600
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004601#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004602 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004603 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004604 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004605 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004606 else
4607 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4608 if (flags & methodVersions[i].flag)
4609 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004610#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004611 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004612 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4613 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004614#endif
4615
4616 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4617 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004618 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004619
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004620#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004621 if (global_ssl.async)
4622 mode |= SSL_MODE_ASYNC;
4623#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004624 SSL_CTX_set_mode(ctx, mode);
4625 srv->ssl_ctx.ctx = ctx;
4626
Emeric Bruna7aa3092012-10-26 12:58:00 +02004627 if (srv->ssl_ctx.client_crt) {
4628 if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004629 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4630 proxy_type_str(curproxy), curproxy->id,
4631 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004632 cfgerr++;
4633 }
4634 else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004635 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4636 proxy_type_str(curproxy), curproxy->id,
4637 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004638 cfgerr++;
4639 }
4640 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004641 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4642 proxy_type_str(curproxy), curproxy->id,
4643 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004644 cfgerr++;
4645 }
4646 }
Emeric Brun94324a42012-10-11 14:00:19 +02004647
Emeric Brun850efd52014-01-29 12:24:34 +01004648 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4649 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004650 switch (srv->ssl_ctx.verify) {
4651 case SSL_SOCK_VERIFY_NONE:
4652 verify = SSL_VERIFY_NONE;
4653 break;
4654 case SSL_SOCK_VERIFY_REQUIRED:
4655 verify = SSL_VERIFY_PEER;
4656 break;
4657 }
Evan Broderbe554312013-06-27 00:05:25 -07004658 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004659 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004660 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004661 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004662 if (srv->ssl_ctx.ca_file) {
4663 /* load CAfile to verify */
4664 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004665 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4666 curproxy->id, srv->id,
4667 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004668 cfgerr++;
4669 }
4670 }
Emeric Brun850efd52014-01-29 12:24:34 +01004671 else {
4672 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004673 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
4674 curproxy->id, srv->id,
4675 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004676 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004677 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4678 curproxy->id, srv->id,
4679 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004680 cfgerr++;
4681 }
Emeric Brunef42d922012-10-11 16:11:36 +02004682#ifdef X509_V_FLAG_CRL_CHECK
4683 if (srv->ssl_ctx.crl_file) {
4684 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4685
4686 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004687 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4688 curproxy->id, srv->id,
4689 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004690 cfgerr++;
4691 }
4692 else {
4693 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4694 }
4695 }
4696#endif
4697 }
4698
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004699 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4700 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4701 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004702 if (srv->ssl_ctx.ciphers &&
4703 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004704 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4705 curproxy->id, srv->id,
4706 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004707 cfgerr++;
4708 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004709
4710#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
4711 if (srv->ssl_ctx.ciphersuites &&
4712 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
4713 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4714 curproxy->id, srv->id,
4715 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4716 cfgerr++;
4717 }
4718#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004719#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4720 if (srv->ssl_ctx.npn_str)
4721 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4722#endif
4723#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4724 if (srv->ssl_ctx.alpn_str)
4725 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4726#endif
4727
Emeric Brun94324a42012-10-11 14:00:19 +02004728
4729 return cfgerr;
4730}
4731
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004732/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004733 * be NULL, in which case nothing is done. Returns the number of errors
4734 * encountered.
4735 */
Willy Tarreau03209342016-12-22 17:08:28 +01004736int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004737{
4738 struct ebmb_node *node;
4739 struct sni_ctx *sni;
4740 int err = 0;
4741
Willy Tarreaufce03112015-01-15 21:32:40 +01004742 /* Automatic memory computations need to know we use SSL there */
4743 global.ssl_used_frontend = 1;
4744
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004745 /* Make sure openssl opens /dev/urandom before the chroot */
4746 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004747 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004748 err++;
4749 }
4750 /* Create initial_ctx used to start the ssl connection before do switchctx */
4751 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004752 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004753 /* It should not be necessary to call this function, but it's
4754 necessary first to check and move all initialisation related
4755 to initial_ctx in ssl_sock_initial_ctx. */
4756 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4757 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004758 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004759 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004760
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004761 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004762 while (node) {
4763 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004764 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4765 /* only initialize the CTX on its first occurrence and
4766 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004767 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004768 node = ebmb_next(node);
4769 }
4770
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004771 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004772 while (node) {
4773 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004774 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4775 /* only initialize the CTX on its first occurrence and
4776 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004777 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004778 node = ebmb_next(node);
4779 }
4780 return err;
4781}
4782
Willy Tarreau55d37912016-12-21 23:38:39 +01004783/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4784 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4785 * alerts are directly emitted since the rest of the stack does it below.
4786 */
4787int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4788{
4789 struct proxy *px = bind_conf->frontend;
4790 int alloc_ctx;
4791 int err;
4792
4793 if (!bind_conf->is_ssl) {
4794 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004795 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4796 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004797 }
4798 return 0;
4799 }
4800 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004801 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004802 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4803 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004804 }
4805 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004806 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4807 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004808 return -1;
4809 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004810 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004811 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004812 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004813 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004814 sizeof(*sh_ssl_sess_tree),
4815 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004816 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004817 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4818 ha_alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
4819 else
4820 ha_alert("Unable to allocate SSL session cache.\n");
4821 return -1;
4822 }
4823 /* free block callback */
4824 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4825 /* init the root tree within the extra space */
4826 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4827 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004828 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004829 err = 0;
4830 /* initialize all certificate contexts */
4831 err += ssl_sock_prepare_all_ctx(bind_conf);
4832
4833 /* initialize CA variables if the certificates generation is enabled */
4834 err += ssl_sock_load_ca(bind_conf);
4835
4836 return -err;
4837}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004838
4839/* release ssl context allocated for servers. */
4840void ssl_sock_free_srv_ctx(struct server *srv)
4841{
Olivier Houchardc7566002018-11-20 23:33:50 +01004842#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4843 if (srv->ssl_ctx.alpn_str)
4844 free(srv->ssl_ctx.alpn_str);
4845#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004846#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004847 if (srv->ssl_ctx.npn_str)
4848 free(srv->ssl_ctx.npn_str);
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004849 if (srv->ssl_ctx.ctx)
4850 SSL_CTX_free(srv->ssl_ctx.ctx);
Olivier Houchardc7566002018-11-20 23:33:50 +01004851#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004852}
4853
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004854/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004855 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4856 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004857void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004858{
4859 struct ebmb_node *node, *back;
4860 struct sni_ctx *sni;
4861
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004862 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004863 while (node) {
4864 sni = ebmb_entry(node, struct sni_ctx, name);
4865 back = ebmb_next(node);
4866 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004867 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004868 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004869 ssl_sock_free_ssl_conf(sni->conf);
4870 free(sni->conf);
4871 sni->conf = NULL;
4872 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004873 free(sni);
4874 node = back;
4875 }
4876
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004877 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004878 while (node) {
4879 sni = ebmb_entry(node, struct sni_ctx, name);
4880 back = ebmb_next(node);
4881 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004882 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004883 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004884 ssl_sock_free_ssl_conf(sni->conf);
4885 free(sni->conf);
4886 sni->conf = NULL;
4887 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004888 free(sni);
4889 node = back;
4890 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004891 SSL_CTX_free(bind_conf->initial_ctx);
4892 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004893 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004894 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004895}
4896
Willy Tarreau795cdab2016-12-22 17:30:54 +01004897/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4898void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4899{
4900 ssl_sock_free_ca(bind_conf);
4901 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004902 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004903 free(bind_conf->ca_sign_file);
4904 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004905 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004906 free(bind_conf->keys_ref->filename);
4907 free(bind_conf->keys_ref->tlskeys);
4908 LIST_DEL(&bind_conf->keys_ref->list);
4909 free(bind_conf->keys_ref);
4910 }
4911 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004912 bind_conf->ca_sign_pass = NULL;
4913 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004914}
4915
Christopher Faulet31af49d2015-06-09 17:29:50 +02004916/* Load CA cert file and private key used to generate certificates */
4917int
Willy Tarreau03209342016-12-22 17:08:28 +01004918ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004919{
Willy Tarreau03209342016-12-22 17:08:28 +01004920 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004921 FILE *fp;
4922 X509 *cacert = NULL;
4923 EVP_PKEY *capkey = NULL;
4924 int err = 0;
4925
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004926 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004927 return err;
4928
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004929#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004930 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004931 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004932 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004933 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004934 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004935#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004936
Christopher Faulet31af49d2015-06-09 17:29:50 +02004937 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004938 ha_alert("Proxy '%s': cannot enable certificate generation, "
4939 "no CA certificate File configured at [%s:%d].\n",
4940 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004941 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004942 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004943
4944 /* read in the CA certificate */
4945 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004946 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4947 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004948 goto load_error;
4949 }
4950 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004951 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4952 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004953 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004954 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004955 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004956 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004957 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4958 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004959 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004960 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004961
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004962 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004963 bind_conf->ca_sign_cert = cacert;
4964 bind_conf->ca_sign_pkey = capkey;
4965 return err;
4966
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004967 read_error:
4968 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004969 if (capkey) EVP_PKEY_free(capkey);
4970 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004971 load_error:
4972 bind_conf->generate_certs = 0;
4973 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004974 return err;
4975}
4976
4977/* Release CA cert and private key used to generate certificated */
4978void
4979ssl_sock_free_ca(struct bind_conf *bind_conf)
4980{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004981 if (bind_conf->ca_sign_pkey)
4982 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4983 if (bind_conf->ca_sign_cert)
4984 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004985 bind_conf->ca_sign_pkey = NULL;
4986 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004987}
4988
Emeric Brun46591952012-05-18 15:47:34 +02004989/*
4990 * This function is called if SSL * context is not yet allocated. The function
4991 * is designed to be called before any other data-layer operation and sets the
4992 * handshake flag on the connection. It is safe to call it multiple times.
4993 * It returns 0 on success and -1 in error case.
4994 */
4995static int ssl_sock_init(struct connection *conn)
4996{
4997 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004998 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004999 return 0;
5000
Willy Tarreau3c728722014-01-23 13:50:42 +01005001 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005002 return 0;
5003
Willy Tarreau20879a02012-12-03 16:32:10 +01005004 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5005 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005006 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005007 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005008
Emeric Brun46591952012-05-18 15:47:34 +02005009 /* If it is in client mode initiate SSL session
5010 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005011 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005012 int may_retry = 1;
5013
5014 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005015 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005016 conn->xprt_ctx = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005017 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005018 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005019 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005020 goto retry_connect;
5021 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005022 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005023 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005024 }
Emeric Brun46591952012-05-18 15:47:34 +02005025
Emeric Brun46591952012-05-18 15:47:34 +02005026 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005027 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005028 SSL_free(conn->xprt_ctx);
5029 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005030 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005031 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005032 goto retry_connect;
5033 }
Emeric Brun55476152014-11-12 17:35:37 +01005034 conn->err_code = CO_ER_SSL_NO_MEM;
5035 return -1;
5036 }
Emeric Brun46591952012-05-18 15:47:34 +02005037
Evan Broderbe554312013-06-27 00:05:25 -07005038 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005039 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005040 SSL_free(conn->xprt_ctx);
5041 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005042 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005043 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005044 goto retry_connect;
5045 }
Emeric Brun55476152014-11-12 17:35:37 +01005046 conn->err_code = CO_ER_SSL_NO_MEM;
5047 return -1;
5048 }
5049
5050 SSL_set_connect_state(conn->xprt_ctx);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005051 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5052 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5053 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
5054 if (sess && !SSL_set_session(conn->xprt_ctx, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005055 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005056 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5057 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005058 } else if (sess) {
5059 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005060 }
5061 }
Evan Broderbe554312013-06-27 00:05:25 -07005062
Emeric Brun46591952012-05-18 15:47:34 +02005063 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005064 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005065
Emeric Brun7ad43e72018-10-10 14:51:02 +02005066 HA_ATOMIC_ADD(&sslconns, 1);
5067 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005068 return 0;
5069 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005070 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005071 int may_retry = 1;
5072
5073 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005074 /* Alloc a new SSL session ctx */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005075 conn->xprt_ctx = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005076 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005077 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005078 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005079 goto retry_accept;
5080 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005081 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005082 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005083 }
Emeric Brun46591952012-05-18 15:47:34 +02005084
Emeric Brun46591952012-05-18 15:47:34 +02005085 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005086 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005087 SSL_free(conn->xprt_ctx);
5088 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005089 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005090 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005091 goto retry_accept;
5092 }
Emeric Brun55476152014-11-12 17:35:37 +01005093 conn->err_code = CO_ER_SSL_NO_MEM;
5094 return -1;
5095 }
Emeric Brun46591952012-05-18 15:47:34 +02005096
Emeric Brune1f38db2012-09-03 20:36:47 +02005097 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005098 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005099 SSL_free(conn->xprt_ctx);
5100 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005101 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005102 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005103 goto retry_accept;
5104 }
Emeric Brun55476152014-11-12 17:35:37 +01005105 conn->err_code = CO_ER_SSL_NO_MEM;
5106 return -1;
5107 }
5108
5109 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005110
Emeric Brun46591952012-05-18 15:47:34 +02005111 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005112 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005113#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005114 conn->flags |= CO_FL_EARLY_SSL_HS;
5115#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005116
Emeric Brun7ad43e72018-10-10 14:51:02 +02005117 HA_ATOMIC_ADD(&sslconns, 1);
5118 HA_ATOMIC_ADD(&totalsslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005119 return 0;
5120 }
5121 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005122 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005123 return -1;
5124}
5125
5126
5127/* This is the callback which is used when an SSL handshake is pending. It
5128 * updates the FD status if it wants some polling before being called again.
5129 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5130 * otherwise it returns non-zero and removes itself from the connection's
5131 * flags (the bit is provided in <flag> by the caller).
5132 */
5133int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5134{
5135 int ret;
5136
Willy Tarreau3c728722014-01-23 13:50:42 +01005137 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005138 return 0;
5139
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005140 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005141 goto out_error;
5142
Olivier Houchardc2aae742017-09-22 18:26:28 +02005143#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5144 /*
5145 * Check if we have early data. If we do, we have to read them
5146 * before SSL_do_handshake() is called, And there's no way to
5147 * detect early data, except to try to read them
5148 */
5149 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5150 size_t read_data;
5151
5152 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5153 1, &read_data);
5154 if (ret == SSL_READ_EARLY_DATA_ERROR)
5155 goto check_error;
5156 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5157 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5158 return 1;
5159 } else
5160 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5161 }
5162#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005163 /* If we use SSL_do_handshake to process a reneg initiated by
5164 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5165 * Usually SSL_write and SSL_read are used and process implicitly
5166 * the reneg handshake.
5167 * Here we use SSL_peek as a workaround for reneg.
5168 */
5169 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5170 char c;
5171
5172 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5173 if (ret <= 0) {
5174 /* handshake may have not been completed, let's find why */
5175 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005176
Emeric Brun674b7432012-11-08 19:21:55 +01005177 if (ret == SSL_ERROR_WANT_WRITE) {
5178 /* SSL handshake needs to write, L4 connection may not be ready */
5179 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005180 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005181 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005182 return 0;
5183 }
5184 else if (ret == SSL_ERROR_WANT_READ) {
5185 /* handshake may have been completed but we have
5186 * no more data to read.
5187 */
5188 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5189 ret = 1;
5190 goto reneg_ok;
5191 }
5192 /* SSL handshake needs to read, L4 connection is ready */
5193 if (conn->flags & CO_FL_WAIT_L4_CONN)
5194 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5195 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005196 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005197 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005198 return 0;
5199 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005200#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005201 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005202 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005203 return 0;
5204 }
5205#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005206 else if (ret == SSL_ERROR_SYSCALL) {
5207 /* if errno is null, then connection was successfully established */
5208 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5209 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005210 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005211#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005212 conn->err_code = CO_ER_SSL_HANDSHAKE;
5213#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005214 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005215#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005216 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5217 empty_handshake = state == TLS_ST_BEFORE;
5218#else
5219 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5220#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005221 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005222 if (!errno) {
5223 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5224 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5225 else
5226 conn->err_code = CO_ER_SSL_EMPTY;
5227 }
5228 else {
5229 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5230 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5231 else
5232 conn->err_code = CO_ER_SSL_ABORT;
5233 }
5234 }
5235 else {
5236 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5237 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005238 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005239 conn->err_code = CO_ER_SSL_HANDSHAKE;
5240 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005241#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005242 }
Emeric Brun674b7432012-11-08 19:21:55 +01005243 goto out_error;
5244 }
5245 else {
5246 /* Fail on all other handshake errors */
5247 /* Note: OpenSSL may leave unread bytes in the socket's
5248 * buffer, causing an RST to be emitted upon close() on
5249 * TCP sockets. We first try to drain possibly pending
5250 * data to avoid this as much as possible.
5251 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005252 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005253 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005254 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5255 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005256 goto out_error;
5257 }
5258 }
5259 /* read some data: consider handshake completed */
5260 goto reneg_ok;
5261 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005262 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005263check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005264 if (ret != 1) {
5265 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005266 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005267
5268 if (ret == SSL_ERROR_WANT_WRITE) {
5269 /* SSL handshake needs to write, L4 connection may not be ready */
5270 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005271 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005272 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005273 return 0;
5274 }
5275 else if (ret == SSL_ERROR_WANT_READ) {
5276 /* SSL handshake needs to read, L4 connection is ready */
5277 if (conn->flags & CO_FL_WAIT_L4_CONN)
5278 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5279 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005280 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005281 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005282 return 0;
5283 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005284#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005285 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005286 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005287 return 0;
5288 }
5289#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005290 else if (ret == SSL_ERROR_SYSCALL) {
5291 /* if errno is null, then connection was successfully established */
5292 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5293 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005294 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005295#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005296 conn->err_code = CO_ER_SSL_HANDSHAKE;
5297#else
5298 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005299#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005300 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5301 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005302#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005303 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005304#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005305 if (empty_handshake) {
5306 if (!errno) {
5307 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5308 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5309 else
5310 conn->err_code = CO_ER_SSL_EMPTY;
5311 }
5312 else {
5313 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5314 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5315 else
5316 conn->err_code = CO_ER_SSL_ABORT;
5317 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005318 }
5319 else {
5320 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5321 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5322 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005323 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005324 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005325#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005326 }
Willy Tarreau89230192012-09-28 20:22:13 +02005327 goto out_error;
5328 }
Emeric Brun46591952012-05-18 15:47:34 +02005329 else {
5330 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005331 /* Note: OpenSSL may leave unread bytes in the socket's
5332 * buffer, causing an RST to be emitted upon close() on
5333 * TCP sockets. We first try to drain possibly pending
5334 * data to avoid this as much as possible.
5335 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005336 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005337 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005338 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5339 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005340 goto out_error;
5341 }
5342 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005343#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5344 else {
5345 /*
5346 * If the server refused the early data, we have to send a
5347 * 425 to the client, as we no longer have the data to sent
5348 * them again.
5349 */
5350 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5351 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5352 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5353 goto out_error;
5354 }
5355 }
5356 }
5357#endif
5358
Emeric Brun46591952012-05-18 15:47:34 +02005359
Emeric Brun674b7432012-11-08 19:21:55 +01005360reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005361
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005362#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005363 /* ASYNC engine API doesn't support moving read/write
5364 * buffers. So we disable ASYNC mode right after
5365 * the handshake to avoid buffer oveflows.
5366 */
5367 if (global_ssl.async)
5368 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5369#endif
Emeric Brun46591952012-05-18 15:47:34 +02005370 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005371 if (!SSL_session_reused(conn->xprt_ctx)) {
5372 if (objt_server(conn->target)) {
5373 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5374 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5375 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005376 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005377 else {
5378 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5379 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5380 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5381 }
Emeric Brun46591952012-05-18 15:47:34 +02005382 }
5383
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005384#ifdef OPENSSL_IS_BORINGSSL
5385 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5386 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5387#endif
Emeric Brun46591952012-05-18 15:47:34 +02005388 /* The connection is now established at both layers, it's time to leave */
5389 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5390 return 1;
5391
5392 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005393 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005394 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005395 ERR_clear_error();
5396
Emeric Brun9fa89732012-10-04 17:09:56 +02005397 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005398 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5399 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5400 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005401 }
5402
Emeric Brun46591952012-05-18 15:47:34 +02005403 /* Fail on all other handshake errors */
5404 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005405 if (!conn->err_code)
5406 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005407 return 0;
5408}
5409
5410/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005411 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005412 * buffer wraps, in which case a second call may be performed. The connection's
5413 * flags are updated with whatever special event is detected (error, read0,
5414 * empty). The caller is responsible for taking care of those events and
5415 * avoiding the call if inappropriate. The function does not call the
5416 * connection's polling update function, so the caller is responsible for this.
5417 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005418static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005419{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005420 ssize_t ret;
5421 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005422
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005423 conn_refresh_polling_flags(conn);
5424
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005425 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005426 goto out_error;
5427
5428 if (conn->flags & CO_FL_HANDSHAKE)
5429 /* a handshake was requested */
5430 return 0;
5431
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005432 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005433
5434 /* read the largest possible block. For this, we perform only one call
5435 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5436 * in which case we accept to do it once again. A new attempt is made on
5437 * EINTR too.
5438 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005439 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005440 int need_out = 0;
5441
Willy Tarreau591d4452018-06-15 17:21:00 +02005442 try = b_contig_space(buf);
5443 if (!try)
5444 break;
5445
Willy Tarreauabf08d92014-01-14 11:31:27 +01005446 if (try > count)
5447 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005448
Olivier Houchardc2aae742017-09-22 18:26:28 +02005449 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5450 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005451 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005452 done++;
5453 try--;
5454 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005455 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005456 conn->tmp_early_data = -1;
5457 continue;
5458 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005459
Olivier Houchardc2aae742017-09-22 18:26:28 +02005460#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5461 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5462 size_t read_length;
5463
5464 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005465 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005466 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5467 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005468 conn->flags |= CO_FL_EARLY_DATA;
5469 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5470 ret == SSL_READ_EARLY_DATA_FINISH) {
5471 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5472 /*
5473 * We're done reading the early data,
5474 * let's make the handshake
5475 */
5476 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5477 conn->flags |= CO_FL_SSL_WAIT_HS;
5478 need_out = 1;
5479 if (read_length == 0)
5480 break;
5481 }
5482 ret = read_length;
5483 }
5484 } else
5485#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005486 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005487#ifdef OPENSSL_IS_BORINGSSL
5488 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5489 if (SSL_in_early_data(conn->xprt_ctx)) {
5490 if (ret > 0)
5491 conn->flags |= CO_FL_EARLY_DATA;
5492 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005493 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005494 }
5495 }
5496#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005497 if (conn->flags & CO_FL_ERROR) {
5498 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005499 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005500 }
Emeric Brun46591952012-05-18 15:47:34 +02005501 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005502 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005503 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005504 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005505 }
Emeric Brun46591952012-05-18 15:47:34 +02005506 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005507 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005508 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005509 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005510 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005511 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005512#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005513 /* Async mode can be re-enabled, because we're leaving data state.*/
5514 if (global_ssl.async)
5515 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5516#endif
Emeric Brun46591952012-05-18 15:47:34 +02005517 break;
5518 }
5519 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005520 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5521 /* handshake is running, and it may need to re-enable read */
5522 conn->flags |= CO_FL_SSL_WAIT_HS;
5523 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005524#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005525 /* Async mode can be re-enabled, because we're leaving data state.*/
5526 if (global_ssl.async)
5527 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5528#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005529 break;
5530 }
Emeric Brun46591952012-05-18 15:47:34 +02005531 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005532 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005533 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005534 } else if (ret == SSL_ERROR_ZERO_RETURN)
5535 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005536 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5537 * stack before shutting down the connection for
5538 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005539 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5540 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005541 /* otherwise it's a real error */
5542 goto out_error;
5543 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005544 if (need_out)
5545 break;
Emeric Brun46591952012-05-18 15:47:34 +02005546 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005547 leave:
5548 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005549 return done;
5550
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005551 clear_ssl_error:
5552 /* Clear openssl global errors stack */
5553 ssl_sock_dump_errors(conn);
5554 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005555 read0:
5556 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005557 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005558
Emeric Brun46591952012-05-18 15:47:34 +02005559 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005560 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005561 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005562 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005563 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005564 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005565}
5566
5567
Willy Tarreau787db9a2018-06-14 18:31:46 +02005568/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5569 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5570 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005571 * Only one call to send() is performed, unless the buffer wraps, in which case
5572 * a second call may be performed. The connection's flags are updated with
5573 * whatever special event is detected (error, empty). The caller is responsible
5574 * for taking care of those events and avoiding the call if inappropriate. The
5575 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005576 * is responsible for this. The buffer's output is not adjusted, it's up to the
5577 * caller to take care of this. It's up to the caller to update the buffer's
5578 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005579 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005580static 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 +02005581{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005582 ssize_t ret;
5583 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005584
5585 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005586 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005587
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005588 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005589 goto out_error;
5590
5591 if (conn->flags & CO_FL_HANDSHAKE)
5592 /* a handshake was requested */
5593 return 0;
5594
5595 /* send the largest possible block. For this we perform only one call
5596 * to send() unless the buffer wraps and we exactly fill the first hunk,
5597 * in which case we accept to do it once again.
5598 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005599 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005600#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5601 size_t written_data;
5602#endif
5603
Willy Tarreau787db9a2018-06-14 18:31:46 +02005604 try = b_contig_data(buf, done);
5605 if (try > count)
5606 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005607
Willy Tarreau7bed9452014-02-02 02:00:24 +01005608 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005609 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005610 global_ssl.max_record && try > global_ssl.max_record) {
5611 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005612 }
5613 else {
5614 /* we need to keep the information about the fact that
5615 * we're not limiting the upcoming send(), because if it
5616 * fails, we'll have to retry with at least as many data.
5617 */
5618 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5619 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005620
Olivier Houchardc2aae742017-09-22 18:26:28 +02005621#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5622 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5623 unsigned int max_early;
5624
Olivier Houchard522eea72017-11-03 16:27:47 +01005625 if (objt_listener(conn->target))
5626 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5627 else {
5628 if (SSL_get0_session(conn->xprt_ctx))
5629 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5630 else
5631 max_early = 0;
5632 }
5633
Olivier Houchard90084a12017-11-23 18:21:29 +01005634 if (try + conn->sent_early_data > max_early) {
5635 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005636 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005637 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5638 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005639 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005640 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005641 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005642 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005643 if (ret == 1) {
5644 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005645 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005646 if (objt_server(conn->target)) {
5647 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5648 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5649 }
5650
Olivier Houchardc2aae742017-09-22 18:26:28 +02005651 }
5652
5653 } else
5654#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005655 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005656
Emeric Brune1f38db2012-09-03 20:36:47 +02005657 if (conn->flags & CO_FL_ERROR) {
5658 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005659 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005660 }
Emeric Brun46591952012-05-18 15:47:34 +02005661 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005662 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005663 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005664 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005665 }
5666 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005667 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005668
Emeric Brun46591952012-05-18 15:47:34 +02005669 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005670 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5671 /* handshake is running, and it may need to re-enable write */
5672 conn->flags |= CO_FL_SSL_WAIT_HS;
5673 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005674#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005675 /* Async mode can be re-enabled, because we're leaving data state.*/
5676 if (global_ssl.async)
5677 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5678#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005679 break;
5680 }
Emeric Brun46591952012-05-18 15:47:34 +02005681 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005682 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005683 break;
5684 }
5685 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005686 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005687 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005688 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005689#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005690 /* Async mode can be re-enabled, because we're leaving data state.*/
5691 if (global_ssl.async)
5692 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5693#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005694 break;
5695 }
Emeric Brun46591952012-05-18 15:47:34 +02005696 goto out_error;
5697 }
5698 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005699 leave:
5700 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005701 return done;
5702
5703 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005704 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005705 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005706 ERR_clear_error();
5707
Emeric Brun46591952012-05-18 15:47:34 +02005708 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005709 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005710}
5711
Emeric Brun46591952012-05-18 15:47:34 +02005712static void ssl_sock_close(struct connection *conn) {
5713
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005714 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005715#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005716 if (global_ssl.async) {
5717 OSSL_ASYNC_FD all_fd[32], afd;
5718 size_t num_all_fds = 0;
5719 int i;
5720
5721 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5722 if (num_all_fds > 32) {
5723 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5724 return;
5725 }
5726
5727 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5728
5729 /* If an async job is pending, we must try to
5730 to catch the end using polling before calling
5731 SSL_free */
5732 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5733 for (i=0 ; i < num_all_fds ; i++) {
5734 /* switch on an handler designed to
5735 * handle the SSL_free
5736 */
5737 afd = all_fd[i];
5738 fdtab[afd].iocb = ssl_async_fd_free;
5739 fdtab[afd].owner = conn->xprt_ctx;
5740 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005741 /* To ensure that the fd cache won't be used
5742 * and we'll catch a real RD event.
5743 */
5744 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005745 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005746 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005747 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005748 return;
5749 }
Emeric Brun3854e012017-05-17 20:42:48 +02005750 /* Else we can remove the fds from the fdtab
5751 * and call SSL_free.
5752 * note: we do a fd_remove and not a delete
5753 * because the fd is owned by the engine.
5754 * the engine is responsible to close
5755 */
5756 for (i=0 ; i < num_all_fds ; i++)
5757 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005758 }
5759#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005760 SSL_free(conn->xprt_ctx);
5761 conn->xprt_ctx = NULL;
Emeric Brun7ad43e72018-10-10 14:51:02 +02005762 HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005763 }
Emeric Brun46591952012-05-18 15:47:34 +02005764}
5765
5766/* This function tries to perform a clean shutdown on an SSL connection, and in
5767 * any case, flags the connection as reusable if no handshake was in progress.
5768 */
5769static void ssl_sock_shutw(struct connection *conn, int clean)
5770{
5771 if (conn->flags & CO_FL_HANDSHAKE)
5772 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005773 if (!clean)
5774 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005775 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005776 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005777 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005778 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005779 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005780 ERR_clear_error();
5781 }
Emeric Brun46591952012-05-18 15:47:34 +02005782}
5783
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005784/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005785int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005786{
5787 struct pkey_info *pkinfo;
5788 int bits = 0;
5789 int sig = TLSEXT_signature_anonymous;
5790 int len = -1;
5791
5792 if (!ssl_sock_is_ssl(conn))
5793 return 0;
5794
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005795 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005796 if (pkinfo) {
5797 sig = pkinfo->sig;
5798 bits = pkinfo->bits;
5799 } else {
5800 /* multicert and generated cert have no pkey info */
5801 X509 *crt;
5802 EVP_PKEY *pkey;
5803 crt = SSL_get_certificate(conn->xprt_ctx);
5804 if (!crt)
5805 return 0;
5806 pkey = X509_get_pubkey(crt);
5807 if (pkey) {
5808 bits = EVP_PKEY_bits(pkey);
5809 switch(EVP_PKEY_base_id(pkey)) {
5810 case EVP_PKEY_RSA:
5811 sig = TLSEXT_signature_rsa;
5812 break;
5813 case EVP_PKEY_EC:
5814 sig = TLSEXT_signature_ecdsa;
5815 break;
5816 case EVP_PKEY_DSA:
5817 sig = TLSEXT_signature_dsa;
5818 break;
5819 }
5820 EVP_PKEY_free(pkey);
5821 }
5822 }
5823
5824 switch(sig) {
5825 case TLSEXT_signature_rsa:
5826 len = chunk_printf(out, "RSA%d", bits);
5827 break;
5828 case TLSEXT_signature_ecdsa:
5829 len = chunk_printf(out, "EC%d", bits);
5830 break;
5831 case TLSEXT_signature_dsa:
5832 len = chunk_printf(out, "DSA%d", bits);
5833 break;
5834 default:
5835 return 0;
5836 }
5837 if (len < 0)
5838 return 0;
5839 return 1;
5840}
5841
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005842/* used for ppv2 cert signature (can be used for logging) */
5843const char *ssl_sock_get_cert_sig(struct connection *conn)
5844{
5845 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5846 X509 *crt;
5847
5848 if (!ssl_sock_is_ssl(conn))
5849 return NULL;
5850 crt = SSL_get_certificate(conn->xprt_ctx);
5851 if (!crt)
5852 return NULL;
5853 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5854 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5855}
5856
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005857/* used for ppv2 authority */
5858const char *ssl_sock_get_sni(struct connection *conn)
5859{
5860#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5861 if (!ssl_sock_is_ssl(conn))
5862 return NULL;
5863 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5864#else
5865 return 0;
5866#endif
5867}
5868
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005869/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005870const char *ssl_sock_get_cipher_name(struct connection *conn)
5871{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005872 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005873 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005874
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005875 return SSL_get_cipher_name(conn->xprt_ctx);
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_proto_version(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_version(conn->xprt_ctx);
5885}
5886
Willy Tarreau8d598402012-10-22 17:58:39 +02005887/* Extract a serial from a cert, and copy it to a chunk.
5888 * Returns 1 if serial is found and copied, 0 if no serial found and
5889 * -1 if output is not large enough.
5890 */
5891static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005892ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005893{
5894 ASN1_INTEGER *serial;
5895
5896 serial = X509_get_serialNumber(crt);
5897 if (!serial)
5898 return 0;
5899
5900 if (out->size < serial->length)
5901 return -1;
5902
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005903 memcpy(out->area, serial->data, serial->length);
5904 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005905 return 1;
5906}
5907
Emeric Brun43e79582014-10-29 19:03:26 +01005908/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08005909 * Returns 1 if the cert is found and copied, 0 on der conversion failure
5910 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01005911 */
5912static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005913ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005914{
5915 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005916 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005917
5918 len =i2d_X509(crt, NULL);
5919 if (len <= 0)
5920 return 1;
5921
5922 if (out->size < len)
5923 return -1;
5924
5925 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005926 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005927 return 1;
5928}
5929
Emeric Brunce5ad802012-10-22 14:11:22 +02005930
Willy Tarreau83061a82018-07-13 11:56:34 +02005931/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005932 * Returns 1 if serial is found and copied, 0 if no valid time found
5933 * and -1 if output is not large enough.
5934 */
5935static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005936ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005937{
5938 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5939 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5940
5941 if (gentm->length < 12)
5942 return 0;
5943 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5944 return 0;
5945 if (out->size < gentm->length-2)
5946 return -1;
5947
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005948 memcpy(out->area, gentm->data+2, gentm->length-2);
5949 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005950 return 1;
5951 }
5952 else if (tm->type == V_ASN1_UTCTIME) {
5953 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5954
5955 if (utctm->length < 10)
5956 return 0;
5957 if (utctm->data[0] >= 0x35)
5958 return 0;
5959 if (out->size < utctm->length)
5960 return -1;
5961
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005962 memcpy(out->area, utctm->data, utctm->length);
5963 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005964 return 1;
5965 }
5966
5967 return 0;
5968}
5969
Emeric Brun87855892012-10-17 17:39:35 +02005970/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5971 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5972 */
5973static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005974ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5975 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005976{
5977 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005978 ASN1_OBJECT *obj;
5979 ASN1_STRING *data;
5980 const unsigned char *data_ptr;
5981 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005982 int i, j, n;
5983 int cur = 0;
5984 const char *s;
5985 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005986 int name_count;
5987
5988 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005989
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005990 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005991 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005992 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005993 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005994 else
5995 j = i;
5996
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005997 ne = X509_NAME_get_entry(a, j);
5998 obj = X509_NAME_ENTRY_get_object(ne);
5999 data = X509_NAME_ENTRY_get_data(ne);
6000 data_ptr = ASN1_STRING_get0_data(data);
6001 data_len = ASN1_STRING_length(data);
6002 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006003 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006004 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006005 s = tmp;
6006 }
6007
6008 if (chunk_strcasecmp(entry, s) != 0)
6009 continue;
6010
6011 if (pos < 0)
6012 cur--;
6013 else
6014 cur++;
6015
6016 if (cur != pos)
6017 continue;
6018
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006019 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006020 return -1;
6021
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006022 memcpy(out->area, data_ptr, data_len);
6023 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006024 return 1;
6025 }
6026
6027 return 0;
6028
6029}
6030
6031/* Extract and format full DN from a X509_NAME and copy result into a chunk
6032 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6033 */
6034static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006035ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006036{
6037 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006038 ASN1_OBJECT *obj;
6039 ASN1_STRING *data;
6040 const unsigned char *data_ptr;
6041 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006042 int i, n, ln;
6043 int l = 0;
6044 const char *s;
6045 char *p;
6046 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006047 int name_count;
6048
6049
6050 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006051
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006052 out->data = 0;
6053 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006054 for (i = 0; i < name_count; i++) {
6055 ne = X509_NAME_get_entry(a, i);
6056 obj = X509_NAME_ENTRY_get_object(ne);
6057 data = X509_NAME_ENTRY_get_data(ne);
6058 data_ptr = ASN1_STRING_get0_data(data);
6059 data_len = ASN1_STRING_length(data);
6060 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006061 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006062 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006063 s = tmp;
6064 }
6065 ln = strlen(s);
6066
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006067 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006068 if (l > out->size)
6069 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006070 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006071
6072 *(p++)='/';
6073 memcpy(p, s, ln);
6074 p += ln;
6075 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006076 memcpy(p, data_ptr, data_len);
6077 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006078 }
6079
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006080 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006081 return 0;
6082
6083 return 1;
6084}
6085
Willy Tarreau119a4082016-12-22 21:58:38 +01006086/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6087 * to disable SNI.
6088 */
Willy Tarreau63076412015-07-10 11:33:32 +02006089void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6090{
6091#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006092 char *prev_name;
6093
Willy Tarreau63076412015-07-10 11:33:32 +02006094 if (!ssl_sock_is_ssl(conn))
6095 return;
6096
Willy Tarreau119a4082016-12-22 21:58:38 +01006097 /* if the SNI changes, we must destroy the reusable context so that a
6098 * new connection will present a new SNI. As an optimization we could
6099 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6100 * server.
6101 */
6102 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6103 if ((!prev_name && hostname) ||
6104 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6105 SSL_set_session(conn->xprt_ctx, NULL);
6106
Willy Tarreau63076412015-07-10 11:33:32 +02006107 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6108#endif
6109}
6110
Emeric Brun0abf8362014-06-24 18:26:41 +02006111/* Extract peer certificate's common name into the chunk dest
6112 * Returns
6113 * the len of the extracted common name
6114 * or 0 if no CN found in DN
6115 * or -1 on error case (i.e. no peer certificate)
6116 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006117int ssl_sock_get_remote_common_name(struct connection *conn,
6118 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006119{
6120 X509 *crt = NULL;
6121 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006122 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006123 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006124 .area = (char *)&find_cn,
6125 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006126 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006127 int result = -1;
David Safb76832014-05-08 23:42:08 -04006128
6129 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006130 goto out;
David Safb76832014-05-08 23:42:08 -04006131
6132 /* SSL_get_peer_certificate, it increase X509 * ref count */
6133 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6134 if (!crt)
6135 goto out;
6136
6137 name = X509_get_subject_name(crt);
6138 if (!name)
6139 goto out;
David Safb76832014-05-08 23:42:08 -04006140
Emeric Brun0abf8362014-06-24 18:26:41 +02006141 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6142out:
David Safb76832014-05-08 23:42:08 -04006143 if (crt)
6144 X509_free(crt);
6145
6146 return result;
6147}
6148
Dave McCowan328fb582014-07-30 10:39:13 -04006149/* returns 1 if client passed a certificate for this session, 0 if not */
6150int ssl_sock_get_cert_used_sess(struct connection *conn)
6151{
6152 X509 *crt = NULL;
6153
6154 if (!ssl_sock_is_ssl(conn))
6155 return 0;
6156
6157 /* SSL_get_peer_certificate, it increase X509 * ref count */
6158 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6159 if (!crt)
6160 return 0;
6161
6162 X509_free(crt);
6163 return 1;
6164}
6165
6166/* returns 1 if client passed a certificate for this connection, 0 if not */
6167int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006168{
6169 if (!ssl_sock_is_ssl(conn))
6170 return 0;
6171
6172 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6173}
6174
6175/* returns result from SSL verify */
6176unsigned int ssl_sock_get_verify_result(struct connection *conn)
6177{
6178 if (!ssl_sock_is_ssl(conn))
6179 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6180
6181 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6182}
6183
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006184/* Returns the application layer protocol name in <str> and <len> when known.
6185 * Zero is returned if the protocol name was not found, otherwise non-zero is
6186 * returned. The string is allocated in the SSL context and doesn't have to be
6187 * freed by the caller. NPN is also checked if available since older versions
6188 * of openssl (1.0.1) which are more common in field only support this one.
6189 */
6190static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6191{
6192 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6193 return 0;
6194
6195 *str = NULL;
6196
6197#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6198 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6199 if (*str)
6200 return 1;
6201#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006202#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006203 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6204 if (*str)
6205 return 1;
6206#endif
6207 return 0;
6208}
6209
Willy Tarreau7875d092012-09-10 08:20:03 +02006210/***** Below are some sample fetching functions for ACL/patterns *****/
6211
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006212static int
6213smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6214{
6215 struct connection *conn;
6216
6217 conn = objt_conn(smp->sess->origin);
6218 if (!conn || conn->xprt != &ssl_sock)
6219 return 0;
6220
6221 smp->flags = 0;
6222 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006223 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6224 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006225
6226 return 1;
6227}
6228
Emeric Brune64aef12012-09-21 13:15:06 +02006229/* boolean, returns true if client cert was present */
6230static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006231smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006232{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006233 struct connection *conn;
6234
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006235 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006236 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006237 return 0;
6238
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006239 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006240 smp->flags |= SMP_F_MAY_CHANGE;
6241 return 0;
6242 }
6243
6244 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006245 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006246 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006247
6248 return 1;
6249}
6250
Emeric Brun43e79582014-10-29 19:03:26 +01006251/* binary, returns a certificate in a binary chunk (der/raw).
6252 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6253 * should be use.
6254 */
6255static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006256smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006257{
6258 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6259 X509 *crt = NULL;
6260 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006261 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006262 struct connection *conn;
6263
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006264 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006265 if (!conn || conn->xprt != &ssl_sock)
6266 return 0;
6267
6268 if (!(conn->flags & CO_FL_CONNECTED)) {
6269 smp->flags |= SMP_F_MAY_CHANGE;
6270 return 0;
6271 }
6272
6273 if (cert_peer)
6274 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6275 else
6276 crt = SSL_get_certificate(conn->xprt_ctx);
6277
6278 if (!crt)
6279 goto out;
6280
6281 smp_trash = get_trash_chunk();
6282 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6283 goto out;
6284
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006285 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006286 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006287 ret = 1;
6288out:
6289 /* SSL_get_peer_certificate, it increase X509 * ref count */
6290 if (cert_peer && crt)
6291 X509_free(crt);
6292 return ret;
6293}
6294
Emeric Brunba841a12014-04-30 17:05:08 +02006295/* binary, returns serial of certificate in a binary chunk.
6296 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6297 * should be use.
6298 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006299static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006300smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006301{
Emeric Brunba841a12014-04-30 17:05:08 +02006302 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006303 X509 *crt = NULL;
6304 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006305 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006306 struct connection *conn;
6307
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006308 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006309 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006310 return 0;
6311
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006312 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006313 smp->flags |= SMP_F_MAY_CHANGE;
6314 return 0;
6315 }
6316
Emeric Brunba841a12014-04-30 17:05:08 +02006317 if (cert_peer)
6318 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6319 else
6320 crt = SSL_get_certificate(conn->xprt_ctx);
6321
Willy Tarreau8d598402012-10-22 17:58:39 +02006322 if (!crt)
6323 goto out;
6324
Willy Tarreau47ca5452012-12-23 20:22:19 +01006325 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006326 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6327 goto out;
6328
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006329 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006330 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006331 ret = 1;
6332out:
Emeric Brunba841a12014-04-30 17:05:08 +02006333 /* SSL_get_peer_certificate, it increase X509 * ref count */
6334 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006335 X509_free(crt);
6336 return ret;
6337}
Emeric Brune64aef12012-09-21 13:15:06 +02006338
Emeric Brunba841a12014-04-30 17:05:08 +02006339/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6340 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6341 * should be use.
6342 */
James Votha051b4a2013-05-14 20:37:59 +02006343static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006344smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006345{
Emeric Brunba841a12014-04-30 17:05:08 +02006346 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006347 X509 *crt = NULL;
6348 const EVP_MD *digest;
6349 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006350 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006351 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006352
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006353 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006354 if (!conn || conn->xprt != &ssl_sock)
6355 return 0;
6356
6357 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006358 smp->flags |= SMP_F_MAY_CHANGE;
6359 return 0;
6360 }
6361
Emeric Brunba841a12014-04-30 17:05:08 +02006362 if (cert_peer)
6363 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6364 else
6365 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006366 if (!crt)
6367 goto out;
6368
6369 smp_trash = get_trash_chunk();
6370 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006371 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6372 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006373
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006374 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006375 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006376 ret = 1;
6377out:
Emeric Brunba841a12014-04-30 17:05:08 +02006378 /* SSL_get_peer_certificate, it increase X509 * ref count */
6379 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006380 X509_free(crt);
6381 return ret;
6382}
6383
Emeric Brunba841a12014-04-30 17:05:08 +02006384/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6385 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6386 * should be use.
6387 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006388static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006389smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006390{
Emeric Brunba841a12014-04-30 17:05:08 +02006391 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006392 X509 *crt = NULL;
6393 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006394 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006395 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006396
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006397 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006398 if (!conn || conn->xprt != &ssl_sock)
6399 return 0;
6400
6401 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006402 smp->flags |= SMP_F_MAY_CHANGE;
6403 return 0;
6404 }
6405
Emeric Brunba841a12014-04-30 17:05:08 +02006406 if (cert_peer)
6407 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6408 else
6409 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006410 if (!crt)
6411 goto out;
6412
Willy Tarreau47ca5452012-12-23 20:22:19 +01006413 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006414 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6415 goto out;
6416
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006417 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006418 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006419 ret = 1;
6420out:
Emeric Brunba841a12014-04-30 17:05:08 +02006421 /* SSL_get_peer_certificate, it increase X509 * ref count */
6422 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006423 X509_free(crt);
6424 return ret;
6425}
6426
Emeric Brunba841a12014-04-30 17:05:08 +02006427/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6428 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6429 * should be use.
6430 */
Emeric Brun87855892012-10-17 17:39:35 +02006431static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006432smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006433{
Emeric Brunba841a12014-04-30 17:05:08 +02006434 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006435 X509 *crt = NULL;
6436 X509_NAME *name;
6437 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006438 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006439 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006440
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006441 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006442 if (!conn || conn->xprt != &ssl_sock)
6443 return 0;
6444
6445 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006446 smp->flags |= SMP_F_MAY_CHANGE;
6447 return 0;
6448 }
6449
Emeric Brunba841a12014-04-30 17:05:08 +02006450 if (cert_peer)
6451 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6452 else
6453 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006454 if (!crt)
6455 goto out;
6456
6457 name = X509_get_issuer_name(crt);
6458 if (!name)
6459 goto out;
6460
Willy Tarreau47ca5452012-12-23 20:22:19 +01006461 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006462 if (args && args[0].type == ARGT_STR) {
6463 int pos = 1;
6464
6465 if (args[1].type == ARGT_SINT)
6466 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006467
6468 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6469 goto out;
6470 }
6471 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6472 goto out;
6473
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006474 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006475 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006476 ret = 1;
6477out:
Emeric Brunba841a12014-04-30 17:05:08 +02006478 /* SSL_get_peer_certificate, it increase X509 * ref count */
6479 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006480 X509_free(crt);
6481 return ret;
6482}
6483
Emeric Brunba841a12014-04-30 17:05:08 +02006484/* string, returns notbefore date in ASN1_UTCTIME format.
6485 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6486 * should be use.
6487 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006488static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006489smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006490{
Emeric Brunba841a12014-04-30 17:05:08 +02006491 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006492 X509 *crt = NULL;
6493 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006494 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006495 struct connection *conn;
6496
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006497 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006498 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006499 return 0;
6500
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006501 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006502 smp->flags |= SMP_F_MAY_CHANGE;
6503 return 0;
6504 }
6505
Emeric Brunba841a12014-04-30 17:05:08 +02006506 if (cert_peer)
6507 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6508 else
6509 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006510 if (!crt)
6511 goto out;
6512
Willy Tarreau47ca5452012-12-23 20:22:19 +01006513 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006514 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6515 goto out;
6516
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006517 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006518 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006519 ret = 1;
6520out:
Emeric Brunba841a12014-04-30 17:05:08 +02006521 /* SSL_get_peer_certificate, it increase X509 * ref count */
6522 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006523 X509_free(crt);
6524 return ret;
6525}
6526
Emeric Brunba841a12014-04-30 17:05:08 +02006527/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6528 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6529 * should be use.
6530 */
Emeric Brun87855892012-10-17 17:39:35 +02006531static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006532smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006533{
Emeric Brunba841a12014-04-30 17:05:08 +02006534 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006535 X509 *crt = NULL;
6536 X509_NAME *name;
6537 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006538 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006539 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006540
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006541 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006542 if (!conn || conn->xprt != &ssl_sock)
6543 return 0;
6544
6545 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006546 smp->flags |= SMP_F_MAY_CHANGE;
6547 return 0;
6548 }
6549
Emeric Brunba841a12014-04-30 17:05:08 +02006550 if (cert_peer)
6551 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6552 else
6553 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006554 if (!crt)
6555 goto out;
6556
6557 name = X509_get_subject_name(crt);
6558 if (!name)
6559 goto out;
6560
Willy Tarreau47ca5452012-12-23 20:22:19 +01006561 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006562 if (args && args[0].type == ARGT_STR) {
6563 int pos = 1;
6564
6565 if (args[1].type == ARGT_SINT)
6566 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006567
6568 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6569 goto out;
6570 }
6571 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6572 goto out;
6573
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006574 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006575 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006576 ret = 1;
6577out:
Emeric Brunba841a12014-04-30 17:05:08 +02006578 /* SSL_get_peer_certificate, it increase X509 * ref count */
6579 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006580 X509_free(crt);
6581 return ret;
6582}
Emeric Brun9143d372012-12-20 15:44:16 +01006583
6584/* integer, returns true if current session use a client certificate */
6585static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006586smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006587{
6588 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006589 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006590
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006591 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006592 if (!conn || conn->xprt != &ssl_sock)
6593 return 0;
6594
6595 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006596 smp->flags |= SMP_F_MAY_CHANGE;
6597 return 0;
6598 }
6599
6600 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006601 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006602 if (crt) {
6603 X509_free(crt);
6604 }
6605
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006606 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006607 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006608 return 1;
6609}
6610
Emeric Brunba841a12014-04-30 17:05:08 +02006611/* integer, returns the certificate version
6612 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6613 * should be use.
6614 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006615static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006616smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006617{
Emeric Brunba841a12014-04-30 17:05:08 +02006618 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006619 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006620 struct connection *conn;
6621
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006622 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006623 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006624 return 0;
6625
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006626 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006627 smp->flags |= SMP_F_MAY_CHANGE;
6628 return 0;
6629 }
6630
Emeric Brunba841a12014-04-30 17:05:08 +02006631 if (cert_peer)
6632 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6633 else
6634 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006635 if (!crt)
6636 return 0;
6637
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006638 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006639 /* SSL_get_peer_certificate increase X509 * ref count */
6640 if (cert_peer)
6641 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006642 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006643
6644 return 1;
6645}
6646
Emeric Brunba841a12014-04-30 17:05:08 +02006647/* string, returns the certificate's signature algorithm.
6648 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6649 * should be use.
6650 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006651static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006652smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006653{
Emeric Brunba841a12014-04-30 17:05:08 +02006654 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006655 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006656 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006657 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006658 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006659
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006660 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006661 if (!conn || conn->xprt != &ssl_sock)
6662 return 0;
6663
6664 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006665 smp->flags |= SMP_F_MAY_CHANGE;
6666 return 0;
6667 }
6668
Emeric Brunba841a12014-04-30 17:05:08 +02006669 if (cert_peer)
6670 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6671 else
6672 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006673 if (!crt)
6674 return 0;
6675
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006676 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6677 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006678
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006679 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6680 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006681 /* SSL_get_peer_certificate increase X509 * ref count */
6682 if (cert_peer)
6683 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006684 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006685 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006686
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006687 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006688 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006689 smp->data.u.str.data = strlen(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
6694 return 1;
6695}
6696
Emeric Brunba841a12014-04-30 17:05:08 +02006697/* string, returns the certificate's key algorithm.
6698 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6699 * should be use.
6700 */
Emeric Brun521a0112012-10-22 12:22:55 +02006701static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006702smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006703{
Emeric Brunba841a12014-04-30 17:05:08 +02006704 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006705 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006706 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006707 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006708 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006709
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006710 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006711 if (!conn || conn->xprt != &ssl_sock)
6712 return 0;
6713
6714 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006715 smp->flags |= SMP_F_MAY_CHANGE;
6716 return 0;
6717 }
6718
Emeric Brunba841a12014-04-30 17:05:08 +02006719 if (cert_peer)
6720 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6721 else
6722 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006723 if (!crt)
6724 return 0;
6725
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006726 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6727 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006728
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006729 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6730 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006731 /* SSL_get_peer_certificate increase X509 * ref count */
6732 if (cert_peer)
6733 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006734 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006735 }
Emeric Brun521a0112012-10-22 12:22:55 +02006736
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006737 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006738 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006739 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006740 if (cert_peer)
6741 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006742
6743 return 1;
6744}
6745
Emeric Brun645ae792014-04-30 14:21:06 +02006746/* boolean, returns true if front conn. transport layer is SSL.
6747 * This function is also usable on backend conn if the fetch keyword 5th
6748 * char is 'b'.
6749 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006750static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006751smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006752{
Emeric Bruneb8def92018-02-19 15:59:48 +01006753 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6754 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006755
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006756 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006757 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006758 return 1;
6759}
6760
Emeric Brun2525b6b2012-10-18 15:59:43 +02006761/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006762static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006763smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006764{
6765#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006766 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006767
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006768 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006769 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006770 conn->xprt_ctx &&
6771 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006772 return 1;
6773#else
6774 return 0;
6775#endif
6776}
6777
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006778/* boolean, returns true if client session has been resumed.
6779 * This function is also usable on backend conn if the fetch keyword 5th
6780 * char is 'b'.
6781 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006782static int
6783smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6784{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006785 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6786 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6787
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006788
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006789 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006790 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006791 conn->xprt_ctx &&
6792 SSL_session_reused(conn->xprt_ctx);
6793 return 1;
6794}
6795
Emeric Brun645ae792014-04-30 14:21:06 +02006796/* string, returns the used cipher if front conn. transport layer is SSL.
6797 * This function is also usable on backend conn if the fetch keyword 5th
6798 * char is 'b'.
6799 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006800static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006801smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006802{
Emeric Bruneb8def92018-02-19 15:59:48 +01006803 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6804 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006805
Willy Tarreaube508f12016-03-10 11:47:01 +01006806 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006807 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006808 return 0;
6809
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006810 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6811 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006812 return 0;
6813
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006814 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006815 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006816 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006817
6818 return 1;
6819}
6820
Emeric Brun645ae792014-04-30 14:21:06 +02006821/* integer, returns the algoritm's keysize if front conn. transport layer
6822 * is SSL.
6823 * This function is also usable on backend conn if the fetch keyword 5th
6824 * char is 'b'.
6825 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006826static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006827smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006828{
Emeric Bruneb8def92018-02-19 15:59:48 +01006829 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6830 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006831 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006832
Emeric Brun589fcad2012-10-16 14:13:26 +02006833 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006834 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006835 return 0;
6836
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006837 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006838 return 0;
6839
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006840 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006841 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006842
6843 return 1;
6844}
6845
Emeric Brun645ae792014-04-30 14:21:06 +02006846/* integer, returns the used keysize if front conn. transport layer is SSL.
6847 * This function is also usable on backend conn if the fetch keyword 5th
6848 * char is 'b'.
6849 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006850static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006851smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006852{
Emeric Bruneb8def92018-02-19 15:59:48 +01006853 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6854 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006855
Emeric Brun589fcad2012-10-16 14:13:26 +02006856 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006857 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6858 return 0;
6859
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006860 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6861 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006862 return 0;
6863
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006864 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006865
6866 return 1;
6867}
6868
Bernard Spil13c53f82018-02-15 13:34:58 +01006869#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006870static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006871smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006872{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006873 struct connection *conn;
6874
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006875 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006876 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006877
Olivier Houchard6b77f492018-11-22 18:18:29 +01006878 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6879 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006880 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6881 return 0;
6882
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006883 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006884 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006885 (const unsigned char **)&smp->data.u.str.area,
6886 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006887
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006888 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006889 return 0;
6890
6891 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006892}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006893#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006894
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006895#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006896static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006897smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006898{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899 struct connection *conn;
6900
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006901 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006902 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006903
Olivier Houchard6b77f492018-11-22 18:18:29 +01006904 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
6905 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6906
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006907 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006908 return 0;
6909
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006910 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006911 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006912 (const unsigned char **)&smp->data.u.str.area,
6913 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006914
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006915 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006916 return 0;
6917
6918 return 1;
6919}
6920#endif
6921
Emeric Brun645ae792014-04-30 14:21:06 +02006922/* string, returns the used protocol if front conn. transport layer is SSL.
6923 * This function is also usable on backend conn if the fetch keyword 5th
6924 * char is 'b'.
6925 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006926static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006927smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006928{
Emeric Bruneb8def92018-02-19 15:59:48 +01006929 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6930 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006931
Emeric Brun589fcad2012-10-16 14:13:26 +02006932 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006933 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6934 return 0;
6935
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006936 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6937 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006938 return 0;
6939
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006940 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006941 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006942 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006943
6944 return 1;
6945}
6946
Willy Tarreau87b09662015-04-03 00:22:06 +02006947/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006948 * This function is also usable on backend conn if the fetch keyword 5th
6949 * char is 'b'.
6950 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006951#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006952static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006953smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006954{
Emeric Bruneb8def92018-02-19 15:59:48 +01006955 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6956 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006957 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006958
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006959 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006960 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006961
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006962 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6963 return 0;
6964
Willy Tarreau192252e2015-04-04 01:47:55 +02006965 ssl_sess = SSL_get_session(conn->xprt_ctx);
6966 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006967 return 0;
6968
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006969 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6970 (unsigned int *)&smp->data.u.str.data);
6971 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006972 return 0;
6973
6974 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006975}
Patrick Hemmer41966772018-04-28 19:15:48 -04006976#endif
6977
Emeric Brunfe68f682012-10-16 14:59:28 +02006978
Patrick Hemmere0275472018-04-28 19:15:51 -04006979#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6980static int
6981smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6982{
6983 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6984 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6985 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006986 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006987
6988 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6989 return 0;
6990
6991 ssl_sess = SSL_get_session(conn->xprt_ctx);
6992 if (!ssl_sess)
6993 return 0;
6994
6995 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006996 data->data = SSL_SESSION_get_master_key(ssl_sess,
6997 (unsigned char *) data->area,
6998 data->size);
6999 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007000 return 0;
7001
7002 smp->flags = 0;
7003 smp->data.type = SMP_T_BIN;
7004 smp->data.u.str = *data;
7005
7006 return 1;
7007}
7008#endif
7009
Patrick Hemmer41966772018-04-28 19:15:48 -04007010#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007011static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007012smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007013{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007014 struct connection *conn;
7015
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007016 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007017 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007018
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007019 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007020 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7021 return 0;
7022
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007023 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
7024 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007025 return 0;
7026
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007027 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007028 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007029}
Patrick Hemmer41966772018-04-28 19:15:48 -04007030#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007031
David Sc1ad52e2014-04-08 18:48:47 -04007032static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007033smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7034{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007035 struct connection *conn;
7036 struct ssl_capture *capture;
7037
7038 conn = objt_conn(smp->sess->origin);
7039 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7040 return 0;
7041
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007042 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007043 if (!capture)
7044 return 0;
7045
7046 smp->flags = SMP_F_CONST;
7047 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007048 smp->data.u.str.area = capture->ciphersuite;
7049 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007050 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007051}
7052
7053static int
7054smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7055{
Willy Tarreau83061a82018-07-13 11:56:34 +02007056 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007057
7058 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7059 return 0;
7060
7061 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007062 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007063 smp->data.type = SMP_T_BIN;
7064 smp->data.u.str = *data;
7065 return 1;
7066}
7067
7068static int
7069smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7070{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007071 struct connection *conn;
7072 struct ssl_capture *capture;
7073
7074 conn = objt_conn(smp->sess->origin);
7075 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7076 return 0;
7077
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007078 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007079 if (!capture)
7080 return 0;
7081
7082 smp->data.type = SMP_T_SINT;
7083 smp->data.u.sint = capture->xxh64;
7084 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007085}
7086
7087static int
7088smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7089{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007090#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007091 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007092 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007093
7094 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7095 return 0;
7096
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007097 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007098 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007099 const char *str;
7100 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007101 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007102 uint16_t id = (bin[0] << 8) | bin[1];
7103#if defined(OPENSSL_IS_BORINGSSL)
7104 cipher = SSL_get_cipher_by_value(id);
7105#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007106 struct connection *conn = __objt_conn(smp->sess->origin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007107 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7108#endif
7109 str = SSL_CIPHER_get_name(cipher);
7110 if (!str || strcmp(str, "(NONE)") == 0)
7111 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007112 else
7113 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7114 }
7115 smp->data.type = SMP_T_STR;
7116 smp->data.u.str = *data;
7117 return 1;
7118#else
7119 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7120#endif
7121}
7122
Patrick Hemmer41966772018-04-28 19:15:48 -04007123#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007124static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007125smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007126{
Emeric Bruneb8def92018-02-19 15:59:48 +01007127 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7128 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007129 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007130 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007131
7132 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007133 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7134 return 0;
7135
7136 if (!(conn->flags & CO_FL_CONNECTED)) {
7137 smp->flags |= SMP_F_MAY_CHANGE;
7138 return 0;
7139 }
7140
7141 finished_trash = get_trash_chunk();
7142 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007143 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7144 finished_trash->area,
7145 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007146 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007147 finished_len = SSL_get_finished(conn->xprt_ctx,
7148 finished_trash->area,
7149 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007150
7151 if (!finished_len)
7152 return 0;
7153
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007154 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007155 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007156 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007157
7158 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007159}
Patrick Hemmer41966772018-04-28 19:15:48 -04007160#endif
David Sc1ad52e2014-04-08 18:48:47 -04007161
Emeric Brun2525b6b2012-10-18 15:59:43 +02007162/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007163static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007164smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007165{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007166 struct connection *conn;
7167
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007168 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007169 if (!conn || conn->xprt != &ssl_sock)
7170 return 0;
7171
7172 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007173 smp->flags = SMP_F_MAY_CHANGE;
7174 return 0;
7175 }
7176
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007177 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007178 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007179 smp->flags = 0;
7180
7181 return 1;
7182}
7183
Emeric Brun2525b6b2012-10-18 15:59:43 +02007184/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007185static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007186smp_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 +02007187{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007188 struct connection *conn;
7189
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007190 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007191 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007192 return 0;
7193
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007194 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007195 smp->flags = SMP_F_MAY_CHANGE;
7196 return 0;
7197 }
7198
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007199 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007200 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007201 smp->flags = 0;
7202
7203 return 1;
7204}
7205
Emeric Brun2525b6b2012-10-18 15:59:43 +02007206/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007207static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007208smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007209{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007210 struct connection *conn;
7211
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007212 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007213 if (!conn || conn->xprt != &ssl_sock)
7214 return 0;
7215
7216 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007217 smp->flags = SMP_F_MAY_CHANGE;
7218 return 0;
7219 }
7220
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007221 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007222 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007223 smp->flags = 0;
7224
7225 return 1;
7226}
7227
Emeric Brun2525b6b2012-10-18 15:59:43 +02007228/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007229static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007230smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007231{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007232 struct connection *conn;
7233
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007234 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007235 if (!conn || conn->xprt != &ssl_sock)
7236 return 0;
7237
7238 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007239 smp->flags = SMP_F_MAY_CHANGE;
7240 return 0;
7241 }
7242
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007243 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007244 return 0;
7245
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007246 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007247 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007248 smp->flags = 0;
7249
7250 return 1;
7251}
7252
Emeric Brunfb510ea2012-10-05 12:00:26 +02007253/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007254static 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 +02007255{
7256 if (!*args[cur_arg + 1]) {
7257 if (err)
7258 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7259 return ERR_ALERT | ERR_FATAL;
7260 }
7261
Willy Tarreauef934602016-12-22 23:12:01 +01007262 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7263 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007264 else
7265 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007266
Emeric Brund94b3fe2012-09-20 18:23:56 +02007267 return 0;
7268}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007269static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7270{
7271 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7272}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007273
Christopher Faulet31af49d2015-06-09 17:29:50 +02007274/* parse the "ca-sign-file" bind keyword */
7275static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7276{
7277 if (!*args[cur_arg + 1]) {
7278 if (err)
7279 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7280 return ERR_ALERT | ERR_FATAL;
7281 }
7282
Willy Tarreauef934602016-12-22 23:12:01 +01007283 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7284 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007285 else
7286 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7287
7288 return 0;
7289}
7290
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007291/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007292static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7293{
7294 if (!*args[cur_arg + 1]) {
7295 if (err)
7296 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7297 return ERR_ALERT | ERR_FATAL;
7298 }
7299 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7300 return 0;
7301}
7302
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007303/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007304static 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 +02007305{
7306 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007307 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007308 return ERR_ALERT | ERR_FATAL;
7309 }
7310
Emeric Brun76d88952012-10-05 15:47:31 +02007311 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007312 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007313 return 0;
7314}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007315static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7316{
7317 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7318}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007319
7320#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7321/* parse the "ciphersuites" bind keyword */
7322static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7323{
7324 if (!*args[cur_arg + 1]) {
7325 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7326 return ERR_ALERT | ERR_FATAL;
7327 }
7328
7329 free(conf->ciphersuites);
7330 conf->ciphersuites = strdup(args[cur_arg + 1]);
7331 return 0;
7332}
7333static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7334{
7335 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7336}
7337#endif
7338
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007339/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007340static 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 +02007341{
Willy Tarreau38011032013-08-13 16:59:39 +02007342 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007343
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007344 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007345 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007346 return ERR_ALERT | ERR_FATAL;
7347 }
7348
Willy Tarreauef934602016-12-22 23:12:01 +01007349 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7350 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007351 memprintf(err, "'%s' : path too long", args[cur_arg]);
7352 return ERR_ALERT | ERR_FATAL;
7353 }
Willy Tarreauef934602016-12-22 23:12:01 +01007354 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007355 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007356 return ERR_ALERT | ERR_FATAL;
7357
7358 return 0;
7359 }
7360
Willy Tarreau03209342016-12-22 17:08:28 +01007361 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007362 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007363
7364 return 0;
7365}
7366
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007367/* parse the "crt-list" bind keyword */
7368static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7369{
7370 if (!*args[cur_arg + 1]) {
7371 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7372 return ERR_ALERT | ERR_FATAL;
7373 }
7374
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007375 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007376 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007377 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007378 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007379
7380 return 0;
7381}
7382
Emeric Brunfb510ea2012-10-05 12:00:26 +02007383/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007384static 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 +02007385{
Emeric Brun051cdab2012-10-02 19:25:50 +02007386#ifndef X509_V_FLAG_CRL_CHECK
7387 if (err)
7388 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7389 return ERR_ALERT | ERR_FATAL;
7390#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007391 if (!*args[cur_arg + 1]) {
7392 if (err)
7393 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7394 return ERR_ALERT | ERR_FATAL;
7395 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007396
Willy Tarreauef934602016-12-22 23:12:01 +01007397 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7398 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007399 else
7400 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007401
Emeric Brun2b58d042012-09-20 17:10:03 +02007402 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007403#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007404}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007405static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7406{
7407 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7408}
Emeric Brun2b58d042012-09-20 17:10:03 +02007409
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007410/* parse the "curves" bind keyword keyword */
7411static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7412{
7413#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7414 if (!*args[cur_arg + 1]) {
7415 if (err)
7416 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7417 return ERR_ALERT | ERR_FATAL;
7418 }
7419 conf->curves = strdup(args[cur_arg + 1]);
7420 return 0;
7421#else
7422 if (err)
7423 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7424 return ERR_ALERT | ERR_FATAL;
7425#endif
7426}
7427static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7428{
7429 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7430}
7431
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007432/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007433static 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 +02007434{
7435#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7436 if (err)
7437 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7438 return ERR_ALERT | ERR_FATAL;
7439#elif defined(OPENSSL_NO_ECDH)
7440 if (err)
7441 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7442 return ERR_ALERT | ERR_FATAL;
7443#else
7444 if (!*args[cur_arg + 1]) {
7445 if (err)
7446 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7447 return ERR_ALERT | ERR_FATAL;
7448 }
7449
7450 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007451
7452 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007453#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007454}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007455static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7456{
7457 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7458}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007459
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007460/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007461static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7462{
7463 int code;
7464 char *p = args[cur_arg + 1];
7465 unsigned long long *ignerr = &conf->crt_ignerr;
7466
7467 if (!*p) {
7468 if (err)
7469 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7470 return ERR_ALERT | ERR_FATAL;
7471 }
7472
7473 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7474 ignerr = &conf->ca_ignerr;
7475
7476 if (strcmp(p, "all") == 0) {
7477 *ignerr = ~0ULL;
7478 return 0;
7479 }
7480
7481 while (p) {
7482 code = atoi(p);
7483 if ((code <= 0) || (code > 63)) {
7484 if (err)
7485 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7486 args[cur_arg], code, args[cur_arg + 1]);
7487 return ERR_ALERT | ERR_FATAL;
7488 }
7489 *ignerr |= 1ULL << code;
7490 p = strchr(p, ',');
7491 if (p)
7492 p++;
7493 }
7494
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007495 return 0;
7496}
7497
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007498/* parse tls_method_options "no-xxx" and "force-xxx" */
7499static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007500{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007501 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007502 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007503 p = strchr(arg, '-');
7504 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007505 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007506 p++;
7507 if (!strcmp(p, "sslv3"))
7508 v = CONF_SSLV3;
7509 else if (!strcmp(p, "tlsv10"))
7510 v = CONF_TLSV10;
7511 else if (!strcmp(p, "tlsv11"))
7512 v = CONF_TLSV11;
7513 else if (!strcmp(p, "tlsv12"))
7514 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007515 else if (!strcmp(p, "tlsv13"))
7516 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007517 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007518 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007519 if (!strncmp(arg, "no-", 3))
7520 methods->flags |= methodVersions[v].flag;
7521 else if (!strncmp(arg, "force-", 6))
7522 methods->min = methods->max = v;
7523 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007524 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007525 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007526 fail:
7527 if (err)
7528 memprintf(err, "'%s' : option not implemented", arg);
7529 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007530}
7531
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007532static 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 +02007533{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007534 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007535}
7536
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007537static 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 +02007538{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007539 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7540}
7541
7542/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7543static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7544{
7545 uint16_t i, v = 0;
7546 char *argv = args[cur_arg + 1];
7547 if (!*argv) {
7548 if (err)
7549 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7550 return ERR_ALERT | ERR_FATAL;
7551 }
7552 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7553 if (!strcmp(argv, methodVersions[i].name))
7554 v = i;
7555 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007556 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007557 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007558 return ERR_ALERT | ERR_FATAL;
7559 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007560 if (!strcmp("ssl-min-ver", args[cur_arg]))
7561 methods->min = v;
7562 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7563 methods->max = v;
7564 else {
7565 if (err)
7566 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7567 return ERR_ALERT | ERR_FATAL;
7568 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007569 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007570}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007571
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007572static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7573{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007574#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007575 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 +02007576#endif
7577 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7578}
7579
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007580static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7581{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007582 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007583}
7584
7585static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7586{
7587 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7588}
7589
Emeric Brun2d0c4822012-10-02 13:45:20 +02007590/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007591static 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 +02007592{
Emeric Brun89675492012-10-05 13:48:26 +02007593 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007594 return 0;
7595}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007596
Olivier Houchardc2aae742017-09-22 18:26:28 +02007597/* parse the "allow-0rtt" bind keyword */
7598static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7599{
7600 conf->early_data = 1;
7601 return 0;
7602}
7603
7604static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7605{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007606 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007607 return 0;
7608}
7609
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007610/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007611static 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 +02007612{
Bernard Spil13c53f82018-02-15 13:34:58 +01007613#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007614 char *p1, *p2;
7615
7616 if (!*args[cur_arg + 1]) {
7617 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7618 return ERR_ALERT | ERR_FATAL;
7619 }
7620
7621 free(conf->npn_str);
7622
Willy Tarreau3724da12016-02-12 17:11:12 +01007623 /* the NPN string is built as a suite of (<len> <name>)*,
7624 * so we reuse each comma to store the next <len> and need
7625 * one more for the end of the string.
7626 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007627 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007628 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007629 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7630
7631 /* replace commas with the name length */
7632 p1 = conf->npn_str;
7633 p2 = p1 + 1;
7634 while (1) {
7635 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7636 if (!p2)
7637 p2 = p1 + 1 + strlen(p1 + 1);
7638
7639 if (p2 - (p1 + 1) > 255) {
7640 *p2 = '\0';
7641 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7642 return ERR_ALERT | ERR_FATAL;
7643 }
7644
7645 *p1 = p2 - (p1 + 1);
7646 p1 = p2;
7647
7648 if (!*p2)
7649 break;
7650
7651 *(p2++) = '\0';
7652 }
7653 return 0;
7654#else
7655 if (err)
7656 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7657 return ERR_ALERT | ERR_FATAL;
7658#endif
7659}
7660
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007661static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7662{
7663 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7664}
7665
Willy Tarreauab861d32013-04-02 02:30:41 +02007666/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007667static 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 +02007668{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007669#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007670 char *p1, *p2;
7671
7672 if (!*args[cur_arg + 1]) {
7673 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7674 return ERR_ALERT | ERR_FATAL;
7675 }
7676
7677 free(conf->alpn_str);
7678
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007679 /* the ALPN string is built as a suite of (<len> <name>)*,
7680 * so we reuse each comma to store the next <len> and need
7681 * one more for the end of the string.
7682 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007683 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007684 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007685 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7686
7687 /* replace commas with the name length */
7688 p1 = conf->alpn_str;
7689 p2 = p1 + 1;
7690 while (1) {
7691 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7692 if (!p2)
7693 p2 = p1 + 1 + strlen(p1 + 1);
7694
7695 if (p2 - (p1 + 1) > 255) {
7696 *p2 = '\0';
7697 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7698 return ERR_ALERT | ERR_FATAL;
7699 }
7700
7701 *p1 = p2 - (p1 + 1);
7702 p1 = p2;
7703
7704 if (!*p2)
7705 break;
7706
7707 *(p2++) = '\0';
7708 }
7709 return 0;
7710#else
7711 if (err)
7712 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7713 return ERR_ALERT | ERR_FATAL;
7714#endif
7715}
7716
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007717static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7718{
7719 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7720}
7721
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007722/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007723static 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 +02007724{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007725 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007726 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007727
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007728 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7729 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007730#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
7731 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7732 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7733#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007734 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007735 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7736 if (!conf->ssl_conf.ssl_methods.min)
7737 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7738 if (!conf->ssl_conf.ssl_methods.max)
7739 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007740
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007741 return 0;
7742}
7743
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007744/* parse the "prefer-client-ciphers" bind keyword */
7745static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7746{
7747 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7748 return 0;
7749}
7750
Christopher Faulet31af49d2015-06-09 17:29:50 +02007751/* parse the "generate-certificates" bind keyword */
7752static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7753{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007754#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007755 conf->generate_certs = 1;
7756#else
7757 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7758 err && *err ? *err : "");
7759#endif
7760 return 0;
7761}
7762
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007763/* parse the "strict-sni" bind keyword */
7764static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7765{
7766 conf->strict_sni = 1;
7767 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007768}
7769
7770/* parse the "tls-ticket-keys" bind keyword */
7771static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7772{
7773#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7774 FILE *f;
7775 int i = 0;
7776 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007777 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007778
7779 if (!*args[cur_arg + 1]) {
7780 if (err)
7781 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7782 return ERR_ALERT | ERR_FATAL;
7783 }
7784
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007785 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007786 if (keys_ref) {
7787 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007788 conf->keys_ref = keys_ref;
7789 return 0;
7790 }
7791
Vincent Bernat02779b62016-04-03 13:48:43 +02007792 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007793 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007794
7795 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7796 if (err)
7797 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7798 return ERR_ALERT | ERR_FATAL;
7799 }
7800
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007801 keys_ref->filename = strdup(args[cur_arg + 1]);
7802
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007803 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7804 int len = strlen(thisline);
7805 /* Strip newline characters from the end */
7806 if(thisline[len - 1] == '\n')
7807 thisline[--len] = 0;
7808
7809 if(thisline[len - 1] == '\r')
7810 thisline[--len] = 0;
7811
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007812 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 +01007813 if (err)
7814 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007815 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007816 return ERR_ALERT | ERR_FATAL;
7817 }
7818 i++;
7819 }
7820
7821 if (i < TLS_TICKETS_NO) {
7822 if (err)
7823 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 +02007824 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007825 return ERR_ALERT | ERR_FATAL;
7826 }
7827
7828 fclose(f);
7829
7830 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007831 i -= 2;
7832 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007833 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007834 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007835 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007836 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007837
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007838 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7839
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007840 return 0;
7841#else
7842 if (err)
7843 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7844 return ERR_ALERT | ERR_FATAL;
7845#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007846}
7847
Emeric Brund94b3fe2012-09-20 18:23:56 +02007848/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007849static 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 +02007850{
7851 if (!*args[cur_arg + 1]) {
7852 if (err)
7853 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7854 return ERR_ALERT | ERR_FATAL;
7855 }
7856
7857 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007858 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007859 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007860 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007861 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007862 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007863 else {
7864 if (err)
7865 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7866 args[cur_arg], args[cur_arg + 1]);
7867 return ERR_ALERT | ERR_FATAL;
7868 }
7869
7870 return 0;
7871}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007872static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7873{
7874 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7875}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007876
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007877/* parse the "no-ca-names" bind keyword */
7878static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7879{
7880 conf->no_ca_names = 1;
7881 return 0;
7882}
7883static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7884{
7885 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7886}
7887
Willy Tarreau92faadf2012-10-10 23:04:25 +02007888/************** "server" keywords ****************/
7889
Olivier Houchardc7566002018-11-20 23:33:50 +01007890/* parse the "npn" bind keyword */
7891static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7892{
7893#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
7894 char *p1, *p2;
7895
7896 if (!*args[*cur_arg + 1]) {
7897 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
7898 return ERR_ALERT | ERR_FATAL;
7899 }
7900
7901 free(newsrv->ssl_ctx.npn_str);
7902
7903 /* the NPN string is built as a suite of (<len> <name>)*,
7904 * so we reuse each comma to store the next <len> and need
7905 * one more for the end of the string.
7906 */
7907 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
7908 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
7909 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
7910 newsrv->ssl_ctx.npn_len);
7911
7912 /* replace commas with the name length */
7913 p1 = newsrv->ssl_ctx.npn_str;
7914 p2 = p1 + 1;
7915 while (1) {
7916 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
7917 newsrv->ssl_ctx.npn_len - (p1 + 1));
7918 if (!p2)
7919 p2 = p1 + 1 + strlen(p1 + 1);
7920
7921 if (p2 - (p1 + 1) > 255) {
7922 *p2 = '\0';
7923 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7924 return ERR_ALERT | ERR_FATAL;
7925 }
7926
7927 *p1 = p2 - (p1 + 1);
7928 p1 = p2;
7929
7930 if (!*p2)
7931 break;
7932
7933 *(p2++) = '\0';
7934 }
7935 return 0;
7936#else
7937 if (err)
7938 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
7939 return ERR_ALERT | ERR_FATAL;
7940#endif
7941}
7942
7943/* parse the "alpn" bind keyword */
7944static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7945{
7946#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
7947 char *p1, *p2;
7948
7949 if (!*args[*cur_arg + 1]) {
7950 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
7951 return ERR_ALERT | ERR_FATAL;
7952 }
7953
7954 free(newsrv->ssl_ctx.alpn_str);
7955
7956 /* the ALPN string is built as a suite of (<len> <name>)*,
7957 * so we reuse each comma to store the next <len> and need
7958 * one more for the end of the string.
7959 */
7960 newsrv->ssl_ctx.alpn_len = strlen(args[*cur_arg + 1]) + 1;
7961 newsrv->ssl_ctx.alpn_str = calloc(1, newsrv->ssl_ctx.alpn_len + 1);
7962 memcpy(newsrv->ssl_ctx.alpn_str + 1, args[*cur_arg + 1],
7963 newsrv->ssl_ctx.alpn_len);
7964
7965 /* replace commas with the name length */
7966 p1 = newsrv->ssl_ctx.alpn_str;
7967 p2 = p1 + 1;
7968 while (1) {
7969 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.alpn_str +
7970 newsrv->ssl_ctx.alpn_len - (p1 + 1));
7971 if (!p2)
7972 p2 = p1 + 1 + strlen(p1 + 1);
7973
7974 if (p2 - (p1 + 1) > 255) {
7975 *p2 = '\0';
7976 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
7977 return ERR_ALERT | ERR_FATAL;
7978 }
7979
7980 *p1 = p2 - (p1 + 1);
7981 p1 = p2;
7982
7983 if (!*p2)
7984 break;
7985
7986 *(p2++) = '\0';
7987 }
7988 return 0;
7989#else
7990 if (err)
7991 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
7992 return ERR_ALERT | ERR_FATAL;
7993#endif
7994}
7995
Emeric Brunef42d922012-10-11 16:11:36 +02007996/* parse the "ca-file" server keyword */
7997static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7998{
7999 if (!*args[*cur_arg + 1]) {
8000 if (err)
8001 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8002 return ERR_ALERT | ERR_FATAL;
8003 }
8004
Willy Tarreauef934602016-12-22 23:12:01 +01008005 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8006 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008007 else
8008 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8009
8010 return 0;
8011}
8012
Olivier Houchard9130a962017-10-17 17:33:43 +02008013/* parse the "check-sni" server keyword */
8014static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8015{
8016 if (!*args[*cur_arg + 1]) {
8017 if (err)
8018 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8019 return ERR_ALERT | ERR_FATAL;
8020 }
8021
8022 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8023 if (!newsrv->check.sni) {
8024 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8025 return ERR_ALERT | ERR_FATAL;
8026 }
8027 return 0;
8028
8029}
8030
Willy Tarreau92faadf2012-10-10 23:04:25 +02008031/* parse the "check-ssl" server keyword */
8032static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8033{
8034 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008035 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8036 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008037#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8038 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8039 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8040#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008041 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008042 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8043 if (!newsrv->ssl_ctx.methods.min)
8044 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8045 if (!newsrv->ssl_ctx.methods.max)
8046 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8047
Willy Tarreau92faadf2012-10-10 23:04:25 +02008048 return 0;
8049}
8050
8051/* parse the "ciphers" server keyword */
8052static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8053{
8054 if (!*args[*cur_arg + 1]) {
8055 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8056 return ERR_ALERT | ERR_FATAL;
8057 }
8058
8059 free(newsrv->ssl_ctx.ciphers);
8060 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8061 return 0;
8062}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008063
8064#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8065/* parse the "ciphersuites" server keyword */
8066static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8067{
8068 if (!*args[*cur_arg + 1]) {
8069 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8070 return ERR_ALERT | ERR_FATAL;
8071 }
8072
8073 free(newsrv->ssl_ctx.ciphersuites);
8074 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8075 return 0;
8076}
8077#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008078
Emeric Brunef42d922012-10-11 16:11:36 +02008079/* parse the "crl-file" server keyword */
8080static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8081{
8082#ifndef X509_V_FLAG_CRL_CHECK
8083 if (err)
8084 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8085 return ERR_ALERT | ERR_FATAL;
8086#else
8087 if (!*args[*cur_arg + 1]) {
8088 if (err)
8089 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8090 return ERR_ALERT | ERR_FATAL;
8091 }
8092
Willy Tarreauef934602016-12-22 23:12:01 +01008093 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8094 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008095 else
8096 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8097
8098 return 0;
8099#endif
8100}
8101
Emeric Bruna7aa3092012-10-26 12:58:00 +02008102/* parse the "crt" server keyword */
8103static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8104{
8105 if (!*args[*cur_arg + 1]) {
8106 if (err)
8107 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8108 return ERR_ALERT | ERR_FATAL;
8109 }
8110
Willy Tarreauef934602016-12-22 23:12:01 +01008111 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008112 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008113 else
8114 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8115
8116 return 0;
8117}
Emeric Brunef42d922012-10-11 16:11:36 +02008118
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008119/* parse the "no-check-ssl" server keyword */
8120static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8121{
8122 newsrv->check.use_ssl = 0;
8123 free(newsrv->ssl_ctx.ciphers);
8124 newsrv->ssl_ctx.ciphers = NULL;
8125 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8126 return 0;
8127}
8128
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008129/* parse the "no-send-proxy-v2-ssl" server keyword */
8130static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8131{
8132 newsrv->pp_opts &= ~SRV_PP_V2;
8133 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8134 return 0;
8135}
8136
8137/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8138static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8139{
8140 newsrv->pp_opts &= ~SRV_PP_V2;
8141 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8142 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8143 return 0;
8144}
8145
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008146/* parse the "no-ssl" server keyword */
8147static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8148{
8149 newsrv->use_ssl = 0;
8150 free(newsrv->ssl_ctx.ciphers);
8151 newsrv->ssl_ctx.ciphers = NULL;
8152 return 0;
8153}
8154
Olivier Houchard522eea72017-11-03 16:27:47 +01008155/* parse the "allow-0rtt" server keyword */
8156static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8157{
8158 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8159 return 0;
8160}
8161
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008162/* parse the "no-ssl-reuse" server keyword */
8163static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8164{
8165 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8166 return 0;
8167}
8168
Emeric Brunf9c5c472012-10-11 15:28:34 +02008169/* parse the "no-tls-tickets" server keyword */
8170static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8171{
8172 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8173 return 0;
8174}
David Safb76832014-05-08 23:42:08 -04008175/* parse the "send-proxy-v2-ssl" server keyword */
8176static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8177{
8178 newsrv->pp_opts |= SRV_PP_V2;
8179 newsrv->pp_opts |= SRV_PP_V2_SSL;
8180 return 0;
8181}
8182
8183/* parse the "send-proxy-v2-ssl-cn" server keyword */
8184static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8185{
8186 newsrv->pp_opts |= SRV_PP_V2;
8187 newsrv->pp_opts |= SRV_PP_V2_SSL;
8188 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8189 return 0;
8190}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008191
Willy Tarreau732eac42015-07-09 11:40:25 +02008192/* parse the "sni" server keyword */
8193static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8194{
8195#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8196 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8197 return ERR_ALERT | ERR_FATAL;
8198#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008199 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008200
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008201 arg = args[*cur_arg + 1];
8202 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008203 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8204 return ERR_ALERT | ERR_FATAL;
8205 }
8206
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008207 free(newsrv->sni_expr);
8208 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008209
Willy Tarreau732eac42015-07-09 11:40:25 +02008210 return 0;
8211#endif
8212}
8213
Willy Tarreau92faadf2012-10-10 23:04:25 +02008214/* parse the "ssl" server keyword */
8215static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8216{
8217 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008218 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8219 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008220#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8221 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8222 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8223#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008224 return 0;
8225}
8226
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008227/* parse the "ssl-reuse" server keyword */
8228static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8229{
8230 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8231 return 0;
8232}
8233
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008234/* parse the "tls-tickets" server keyword */
8235static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8236{
8237 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8238 return 0;
8239}
8240
Emeric Brunef42d922012-10-11 16:11:36 +02008241/* parse the "verify" server keyword */
8242static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8243{
8244 if (!*args[*cur_arg + 1]) {
8245 if (err)
8246 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8247 return ERR_ALERT | ERR_FATAL;
8248 }
8249
8250 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008251 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008252 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008253 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008254 else {
8255 if (err)
8256 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8257 args[*cur_arg], args[*cur_arg + 1]);
8258 return ERR_ALERT | ERR_FATAL;
8259 }
8260
Evan Broderbe554312013-06-27 00:05:25 -07008261 return 0;
8262}
8263
8264/* parse the "verifyhost" server keyword */
8265static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8266{
8267 if (!*args[*cur_arg + 1]) {
8268 if (err)
8269 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8270 return ERR_ALERT | ERR_FATAL;
8271 }
8272
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008273 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008274 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8275
Emeric Brunef42d922012-10-11 16:11:36 +02008276 return 0;
8277}
8278
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008279/* parse the "ssl-default-bind-options" keyword in global section */
8280static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8281 struct proxy *defpx, const char *file, int line,
8282 char **err) {
8283 int i = 1;
8284
8285 if (*(args[i]) == 0) {
8286 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8287 return -1;
8288 }
8289 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008290 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008291 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008292 else if (!strcmp(args[i], "prefer-client-ciphers"))
8293 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008294 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8295 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8296 i++;
8297 else {
8298 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8299 return -1;
8300 }
8301 }
8302 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008303 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8304 return -1;
8305 }
8306 i++;
8307 }
8308 return 0;
8309}
8310
8311/* parse the "ssl-default-server-options" keyword in global section */
8312static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8313 struct proxy *defpx, const char *file, int line,
8314 char **err) {
8315 int i = 1;
8316
8317 if (*(args[i]) == 0) {
8318 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8319 return -1;
8320 }
8321 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008322 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008323 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008324 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8325 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8326 i++;
8327 else {
8328 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8329 return -1;
8330 }
8331 }
8332 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008333 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8334 return -1;
8335 }
8336 i++;
8337 }
8338 return 0;
8339}
8340
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008341/* parse the "ca-base" / "crt-base" keywords in global section.
8342 * Returns <0 on alert, >0 on warning, 0 on success.
8343 */
8344static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8345 struct proxy *defpx, const char *file, int line,
8346 char **err)
8347{
8348 char **target;
8349
Willy Tarreauef934602016-12-22 23:12:01 +01008350 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008351
8352 if (too_many_args(1, args, err, NULL))
8353 return -1;
8354
8355 if (*target) {
8356 memprintf(err, "'%s' already specified.", args[0]);
8357 return -1;
8358 }
8359
8360 if (*(args[1]) == 0) {
8361 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8362 return -1;
8363 }
8364 *target = strdup(args[1]);
8365 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008366}
8367
8368/* parse the "ssl-mode-async" keyword in global section.
8369 * Returns <0 on alert, >0 on warning, 0 on success.
8370 */
8371static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8372 struct proxy *defpx, const char *file, int line,
8373 char **err)
8374{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008375#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008376 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008377 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008378 return 0;
8379#else
8380 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8381 return -1;
8382#endif
8383}
8384
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008385#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008386static int ssl_check_async_engine_count(void) {
8387 int err_code = 0;
8388
Emeric Brun3854e012017-05-17 20:42:48 +02008389 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008390 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008391 err_code = ERR_ABORT;
8392 }
8393 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008394}
8395
Grant Zhang872f9c22017-01-21 01:10:18 +00008396/* parse the "ssl-engine" keyword in global section.
8397 * Returns <0 on alert, >0 on warning, 0 on success.
8398 */
8399static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8400 struct proxy *defpx, const char *file, int line,
8401 char **err)
8402{
8403 char *algo;
8404 int ret = -1;
8405
8406 if (*(args[1]) == 0) {
8407 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8408 return ret;
8409 }
8410
8411 if (*(args[2]) == 0) {
8412 /* if no list of algorithms is given, it defaults to ALL */
8413 algo = strdup("ALL");
8414 goto add_engine;
8415 }
8416
8417 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8418 if (strcmp(args[2], "algo") != 0) {
8419 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8420 return ret;
8421 }
8422
8423 if (*(args[3]) == 0) {
8424 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8425 return ret;
8426 }
8427 algo = strdup(args[3]);
8428
8429add_engine:
8430 if (ssl_init_single_engine(args[1], algo)==0) {
8431 openssl_engines_initialized++;
8432 ret = 0;
8433 }
8434 free(algo);
8435 return ret;
8436}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008437#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008438
Willy Tarreauf22e9682016-12-21 23:23:19 +01008439/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8440 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8441 */
8442static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8443 struct proxy *defpx, const char *file, int line,
8444 char **err)
8445{
8446 char **target;
8447
Willy Tarreauef934602016-12-22 23:12:01 +01008448 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008449
8450 if (too_many_args(1, args, err, NULL))
8451 return -1;
8452
8453 if (*(args[1]) == 0) {
8454 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8455 return -1;
8456 }
8457
8458 free(*target);
8459 *target = strdup(args[1]);
8460 return 0;
8461}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008462
8463#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
8464/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8465 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8466 */
8467static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8468 struct proxy *defpx, const char *file, int line,
8469 char **err)
8470{
8471 char **target;
8472
8473 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8474
8475 if (too_many_args(1, args, err, NULL))
8476 return -1;
8477
8478 if (*(args[1]) == 0) {
8479 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8480 return -1;
8481 }
8482
8483 free(*target);
8484 *target = strdup(args[1]);
8485 return 0;
8486}
8487#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008488
Willy Tarreau9ceda382016-12-21 23:13:03 +01008489/* parse various global tune.ssl settings consisting in positive integers.
8490 * Returns <0 on alert, >0 on warning, 0 on success.
8491 */
8492static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8493 struct proxy *defpx, const char *file, int line,
8494 char **err)
8495{
8496 int *target;
8497
8498 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8499 target = &global.tune.sslcachesize;
8500 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008501 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008502 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008503 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008504 else if (strcmp(args[0], "maxsslconn") == 0)
8505 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008506 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8507 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008508 else {
8509 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8510 return -1;
8511 }
8512
8513 if (too_many_args(1, args, err, NULL))
8514 return -1;
8515
8516 if (*(args[1]) == 0) {
8517 memprintf(err, "'%s' expects an integer argument.", args[0]);
8518 return -1;
8519 }
8520
8521 *target = atoi(args[1]);
8522 if (*target < 0) {
8523 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8524 return -1;
8525 }
8526 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008527}
8528
8529static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8530 struct proxy *defpx, const char *file, int line,
8531 char **err)
8532{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008533 int ret;
8534
8535 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8536 if (ret != 0)
8537 return ret;
8538
Willy Tarreaubafbe012017-11-24 17:34:44 +01008539 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008540 memprintf(err, "'%s' is already configured.", args[0]);
8541 return -1;
8542 }
8543
Willy Tarreaubafbe012017-11-24 17:34:44 +01008544 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8545 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008546 memprintf(err, "Out of memory error.");
8547 return -1;
8548 }
8549 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008550}
8551
8552/* parse "ssl.force-private-cache".
8553 * Returns <0 on alert, >0 on warning, 0 on success.
8554 */
8555static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8556 struct proxy *defpx, const char *file, int line,
8557 char **err)
8558{
8559 if (too_many_args(0, args, err, NULL))
8560 return -1;
8561
Willy Tarreauef934602016-12-22 23:12:01 +01008562 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008563 return 0;
8564}
8565
8566/* parse "ssl.lifetime".
8567 * Returns <0 on alert, >0 on warning, 0 on success.
8568 */
8569static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8570 struct proxy *defpx, const char *file, int line,
8571 char **err)
8572{
8573 const char *res;
8574
8575 if (too_many_args(1, args, err, NULL))
8576 return -1;
8577
8578 if (*(args[1]) == 0) {
8579 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8580 return -1;
8581 }
8582
Willy Tarreauef934602016-12-22 23:12:01 +01008583 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008584 if (res) {
8585 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8586 return -1;
8587 }
8588 return 0;
8589}
8590
8591#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008592/* parse "ssl-dh-param-file".
8593 * Returns <0 on alert, >0 on warning, 0 on success.
8594 */
8595static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8596 struct proxy *defpx, const char *file, int line,
8597 char **err)
8598{
8599 if (too_many_args(1, args, err, NULL))
8600 return -1;
8601
8602 if (*(args[1]) == 0) {
8603 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8604 return -1;
8605 }
8606
8607 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8608 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8609 return -1;
8610 }
8611 return 0;
8612}
8613
Willy Tarreau9ceda382016-12-21 23:13:03 +01008614/* parse "ssl.default-dh-param".
8615 * Returns <0 on alert, >0 on warning, 0 on success.
8616 */
8617static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8618 struct proxy *defpx, const char *file, int line,
8619 char **err)
8620{
8621 if (too_many_args(1, args, err, NULL))
8622 return -1;
8623
8624 if (*(args[1]) == 0) {
8625 memprintf(err, "'%s' expects an integer argument.", args[0]);
8626 return -1;
8627 }
8628
Willy Tarreauef934602016-12-22 23:12:01 +01008629 global_ssl.default_dh_param = atoi(args[1]);
8630 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008631 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8632 return -1;
8633 }
8634 return 0;
8635}
8636#endif
8637
8638
William Lallemand32af2032016-10-29 18:09:35 +02008639/* This function is used with TLS ticket keys management. It permits to browse
8640 * each reference. The variable <getnext> must contain the current node,
8641 * <end> point to the root node.
8642 */
8643#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8644static inline
8645struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8646{
8647 struct tls_keys_ref *ref = getnext;
8648
8649 while (1) {
8650
8651 /* Get next list entry. */
8652 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8653
8654 /* If the entry is the last of the list, return NULL. */
8655 if (&ref->list == end)
8656 return NULL;
8657
8658 return ref;
8659 }
8660}
8661
8662static inline
8663struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8664{
8665 int id;
8666 char *error;
8667
8668 /* If the reference starts by a '#', this is numeric id. */
8669 if (reference[0] == '#') {
8670 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8671 id = strtol(reference + 1, &error, 10);
8672 if (*error != '\0')
8673 return NULL;
8674
8675 /* Perform the unique id lookup. */
8676 return tlskeys_ref_lookupid(id);
8677 }
8678
8679 /* Perform the string lookup. */
8680 return tlskeys_ref_lookup(reference);
8681}
8682#endif
8683
8684
8685#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8686
8687static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8688
8689static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8690 return cli_io_handler_tlskeys_files(appctx);
8691}
8692
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008693/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8694 * (next index to be dumped), and cli.p0 (next key reference).
8695 */
William Lallemand32af2032016-10-29 18:09:35 +02008696static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8697
8698 struct stream_interface *si = appctx->owner;
8699
8700 switch (appctx->st2) {
8701 case STAT_ST_INIT:
8702 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08008703 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02008704 * later and restart at the state "STAT_ST_INIT".
8705 */
8706 chunk_reset(&trash);
8707
8708 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8709 chunk_appendf(&trash, "# id secret\n");
8710 else
8711 chunk_appendf(&trash, "# id (file)\n");
8712
Willy Tarreau06d80a92017-10-19 14:32:15 +02008713 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01008714 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008715 return 0;
8716 }
8717
William Lallemand32af2032016-10-29 18:09:35 +02008718 /* Now, we start the browsing of the references lists.
8719 * Note that the following call to LIST_ELEM return bad pointer. The only
8720 * available field of this pointer is <list>. It is used with the function
8721 * tlskeys_list_get_next() for retruning the first available entry
8722 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008723 if (appctx->ctx.cli.p0 == NULL) {
8724 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8725 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008726 }
8727
8728 appctx->st2 = STAT_ST_LIST;
8729 /* fall through */
8730
8731 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008732 while (appctx->ctx.cli.p0) {
8733 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008734
8735 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008736 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008737 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008738
8739 if (appctx->ctx.cli.i1 == 0)
8740 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8741
William Lallemand32af2032016-10-29 18:09:35 +02008742 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008743 int head;
8744
8745 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8746 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008747 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008748 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008749
8750 chunk_reset(t2);
8751 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008752 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8753 sizeof(struct tls_sess_key),
8754 t2->area, t2->size);
8755 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8756 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008757
Willy Tarreau06d80a92017-10-19 14:32:15 +02008758 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008759 /* let's try again later from this stream. We add ourselves into
8760 * this stream's users so that it can remove us upon termination.
8761 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008762 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01008763 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008764 return 0;
8765 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008766 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008767 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008768 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008769 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008770 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008771 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008772 /* let's try again later from this stream. We add ourselves into
8773 * this stream's users so that it can remove us upon termination.
8774 */
Willy Tarreaudb398432018-11-15 11:08:52 +01008775 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02008776 return 0;
8777 }
8778
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008779 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008780 break;
8781
8782 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008783 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008784 }
8785
8786 appctx->st2 = STAT_ST_FIN;
8787 /* fall through */
8788
8789 default:
8790 appctx->st2 = STAT_ST_FIN;
8791 return 1;
8792 }
8793 return 0;
8794}
8795
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008796/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008797static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008798{
William Lallemand32af2032016-10-29 18:09:35 +02008799 /* no parameter, shows only file list */
8800 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008801 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008802 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008803 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008804 }
8805
8806 if (args[2][0] == '*') {
8807 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008808 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008809 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008810 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8811 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008812 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008813 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008814 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008815 return 1;
8816 }
8817 }
William Lallemand32af2032016-10-29 18:09:35 +02008818 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008819 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008820}
8821
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008822static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008823{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008824 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008825 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008826
William Lallemand32af2032016-10-29 18:09:35 +02008827 /* Expect two parameters: the filename and the new new TLS key in encoding */
8828 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008829 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008830 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 +01008831 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008832 return 1;
8833 }
8834
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008835 ref = tlskeys_ref_lookup_ref(args[3]);
8836 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008837 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008838 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008839 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008840 return 1;
8841 }
8842
Willy Tarreau1c913e42018-08-22 05:26:57 +02008843 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8844 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008845 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008846 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008847 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008848 return 1;
8849 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008850 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008851 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008852 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008853 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008854 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008855 return 1;
8856
8857}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008858#endif
William Lallemand32af2032016-10-29 18:09:35 +02008859
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008860static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008861{
8862#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8863 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008864 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008865
8866 if (!payload)
8867 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008868
8869 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008870 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008871 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008872 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008873 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008874 return 1;
8875 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008876
8877 /* remove \r and \n from the payload */
8878 for (i = 0, j = 0; payload[i]; i++) {
8879 if (payload[i] == '\r' || payload[i] == '\n')
8880 continue;
8881 payload[j++] = payload[i];
8882 }
8883 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008884
Willy Tarreau1c913e42018-08-22 05:26:57 +02008885 ret = base64dec(payload, j, trash.area, trash.size);
8886 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008887 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008888 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008889 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008890 return 1;
8891 }
8892
Willy Tarreau1c913e42018-08-22 05:26:57 +02008893 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008894 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8895 if (err) {
8896 memprintf(&err, "%s.\n", err);
8897 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008898 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008899 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008900 else {
8901 appctx->ctx.cli.severity = LOG_ERR;
8902 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8903 appctx->st0 = CLI_ST_PRINT;
8904 }
William Lallemand32af2032016-10-29 18:09:35 +02008905 return 1;
8906 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008907 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008908 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008909 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008910 return 1;
8911#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008912 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008913 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 +01008914 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008915 return 1;
8916#endif
8917
8918}
8919
8920/* register cli keywords */
8921static struct cli_kw_list cli_kws = {{ },{
8922#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8923 { { "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 +02008924 { { "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 +02008925#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008926 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008927 { { NULL }, NULL, NULL, NULL }
8928}};
8929
Willy Tarreau0108d902018-11-25 19:14:37 +01008930INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008931
Willy Tarreau7875d092012-09-10 08:20:03 +02008932/* Note: must not be declared <const> as its list will be overwritten.
8933 * Please take care of keeping this list alphabetically sorted.
8934 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008935static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008936 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008937 { "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 +01008938#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8939 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8940#endif
Emeric Brun645ae792014-04-30 14:21:06 +02008941 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01008942#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8943 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
8944#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008945 { "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 +02008946 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008947 { "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 +02008948 { "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 -04008949#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008950 { "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 -04008951#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008952#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8953 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8954#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008955 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8956 { "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 +01008957 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008958 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008959 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8960 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8961 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8962 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8963 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8964 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8965 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8966 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008967 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008968 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8969 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008970 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008971 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8972 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8973 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8974 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8975 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8976 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8977 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008978 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008979 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008980 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008981 { "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 +01008982 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008983 { "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 +02008984 { "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 +01008985 { "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 +02008986 { "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 +01008987#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008988 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008989#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008990#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008991 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008992#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008993 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008994#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02008995 { "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 -04008996#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008997 { "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 -04008998#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008999 { "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 -04009000#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04009001#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
9002 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9003#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009004#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009005 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009006#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009007 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9008 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9009 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9010 { "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 +02009011 { NULL, NULL, 0, 0, 0 },
9012}};
9013
Willy Tarreau0108d902018-11-25 19:14:37 +01009014INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9015
Willy Tarreau7875d092012-09-10 08:20:03 +02009016/* Note: must not be declared <const> as its list will be overwritten.
9017 * Please take care of keeping this list alphabetically sorted.
9018 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009019static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009020 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9021 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009022 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009023}};
9024
Willy Tarreau0108d902018-11-25 19:14:37 +01009025INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9026
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009027/* Note: must not be declared <const> as its list will be overwritten.
9028 * Please take care of keeping this list alphabetically sorted, doing so helps
9029 * all code contributors.
9030 * Optional keywords are also declared with a NULL ->parse() function so that
9031 * the config parser can report an appropriate error when a known keyword was
9032 * not enabled.
9033 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009034static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009035 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009036 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9037 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9038 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009039#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9040 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9041#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009042 { "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 +01009043 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009044 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009045 { "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 +01009046 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009047 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9048 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009049 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9050 { NULL, NULL, 0 },
9051};
9052
Willy Tarreau0108d902018-11-25 19:14:37 +01009053/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9054
Willy Tarreau51fb7652012-09-18 18:24:39 +02009055static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009056 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009057 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9058 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9059 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9060 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9061 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9062 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009063#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9064 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9065#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009066 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9067 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9068 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9069 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9070 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9071 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9072 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9073 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9074 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9075 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009076 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009077 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009078 { "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 +02009079 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9080 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9081 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9082 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009083 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009084 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9085 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009086 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9087 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009088 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9089 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9090 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9091 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9092 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009093 { NULL, NULL, 0 },
9094}};
Emeric Brun46591952012-05-18 15:47:34 +02009095
Willy Tarreau0108d902018-11-25 19:14:37 +01009096INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9097
Willy Tarreau92faadf2012-10-10 23:04:25 +02009098/* Note: must not be declared <const> as its list will be overwritten.
9099 * Please take care of keeping this list alphabetically sorted, doing so helps
9100 * all code contributors.
9101 * Optional keywords are also declared with a NULL ->parse() function so that
9102 * the config parser can report an appropriate error when a known keyword was
9103 * not enabled.
9104 */
9105static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009106 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009107 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009108 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02009109 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009110 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9111 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009112#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9113 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9114#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009115 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9116 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9117 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9118 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9119 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9120 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9121 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9122 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9123 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9124 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9125 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9126 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9127 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9128 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9129 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9130 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9131 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9132 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009133 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009134 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9135 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9136 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9137 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9138 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9139 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9140 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9141 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9142 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9143 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009144 { NULL, NULL, 0, 0 },
9145}};
9146
Willy Tarreau0108d902018-11-25 19:14:37 +01009147INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9148
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009149static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009150 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9151 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009152 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009153 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9154 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009155#ifndef OPENSSL_NO_DH
9156 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9157#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009158 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009159#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009160 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009161#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009162 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9163#ifndef OPENSSL_NO_DH
9164 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9165#endif
9166 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9167 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9168 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9169 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009170 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009171 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9172 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009173#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9174 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9175 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9176#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009177 { 0, NULL, NULL },
9178}};
9179
Willy Tarreau0108d902018-11-25 19:14:37 +01009180INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9181
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009182/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009183static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009184 .snd_buf = ssl_sock_from_buf,
9185 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02009186 .subscribe = conn_subscribe,
Olivier Houchard83a0cd82018-09-28 17:57:58 +02009187 .unsubscribe = conn_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009188 .rcv_pipe = NULL,
9189 .snd_pipe = NULL,
9190 .shutr = NULL,
9191 .shutw = ssl_sock_shutw,
9192 .close = ssl_sock_close,
9193 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009194 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009195 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009196 .prepare_srv = ssl_sock_prepare_srv_ctx,
9197 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009198 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009199 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009200};
9201
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009202enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9203 struct session *sess, struct stream *s, int flags)
9204{
9205 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009206 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009207
9208 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009209 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009210
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009211 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009212 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009213 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009214 s->req.flags |= CF_READ_NULL;
9215 return ACT_RET_YIELD;
9216 }
9217 }
9218 return (ACT_RET_CONT);
9219}
9220
9221static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9222{
9223 rule->action_ptr = ssl_action_wait_for_hs;
9224
9225 return ACT_RET_PRS_OK;
9226}
9227
9228static struct action_kw_list http_req_actions = {ILH, {
9229 { "wait-for-handshake", ssl_parse_wait_for_hs },
9230 { /* END */ }
9231}};
9232
Willy Tarreau0108d902018-11-25 19:14:37 +01009233INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9234
Daniel Jakots54ffb912015-11-06 20:02:41 +01009235#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009236
9237static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9238{
9239 if (ptr) {
9240 chunk_destroy(ptr);
9241 free(ptr);
9242 }
9243}
9244
9245#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009246static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9247{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009248 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009249}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009250
Emeric Brun46591952012-05-18 15:47:34 +02009251__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009252static void __ssl_sock_init(void)
9253{
Emeric Brun46591952012-05-18 15:47:34 +02009254 STACK_OF(SSL_COMP)* cm;
9255
Willy Tarreauef934602016-12-22 23:12:01 +01009256 if (global_ssl.listen_default_ciphers)
9257 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9258 if (global_ssl.connect_default_ciphers)
9259 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009260#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
9261 if (global_ssl.listen_default_ciphersuites)
9262 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9263 if (global_ssl.connect_default_ciphersuites)
9264 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9265#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009266
Willy Tarreau13e14102016-12-22 20:25:26 +01009267 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02009268 SSL_library_init();
9269 cm = SSL_COMP_get_compression_methods();
9270 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009271#ifdef USE_THREAD
9272 ssl_locking_init();
9273#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01009274#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009275 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9276#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009277 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009278 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 +01009279 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009280#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009281 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009282 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009283#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009284#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9285 hap_register_post_check(tlskeys_finalize_config);
9286#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009287
9288 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9289 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9290
9291#ifndef OPENSSL_NO_DH
9292 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9293 hap_register_post_deinit(ssl_free_dh);
9294#endif
9295#ifndef OPENSSL_NO_ENGINE
9296 hap_register_post_deinit(ssl_free_engines);
9297#endif
9298 /* Load SSL string for the verbose & debug mode. */
9299 ERR_load_SSL_strings();
9300}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009301
Willy Tarreau80713382018-11-26 10:19:54 +01009302/* Compute and register the version string */
9303static void ssl_register_build_options()
9304{
9305 char *ptr = NULL;
9306 int i;
9307
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009308 memprintf(&ptr, "Built with OpenSSL version : "
9309#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009310 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009311#else /* OPENSSL_IS_BORINGSSL */
9312 OPENSSL_VERSION_TEXT
9313 "\nRunning on OpenSSL version : %s%s",
9314 SSLeay_version(SSLEAY_VERSION),
9315 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9316#endif
9317 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9318#if OPENSSL_VERSION_NUMBER < 0x00907000L
9319 "no (library version too old)"
9320#elif defined(OPENSSL_NO_TLSEXT)
9321 "no (disabled via OPENSSL_NO_TLSEXT)"
9322#else
9323 "yes"
9324#endif
9325 "", ptr);
9326
9327 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9328#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9329 "yes"
9330#else
9331#ifdef OPENSSL_NO_TLSEXT
9332 "no (because of OPENSSL_NO_TLSEXT)"
9333#else
9334 "no (version might be too old, 0.9.8f min needed)"
9335#endif
9336#endif
9337 "", ptr);
9338
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009339 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9340 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9341 if (methodVersions[i].option)
9342 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009343
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009344 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009345}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009346
Willy Tarreau80713382018-11-26 10:19:54 +01009347INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009348
Emeric Brun46591952012-05-18 15:47:34 +02009349
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009350#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009351void ssl_free_engines(void) {
9352 struct ssl_engine_list *wl, *wlb;
9353 /* free up engine list */
9354 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9355 ENGINE_finish(wl->e);
9356 ENGINE_free(wl->e);
9357 LIST_DEL(&wl->list);
9358 free(wl);
9359 }
9360}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009361#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009362
Remi Gacogned3a23c32015-05-28 16:39:47 +02009363#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009364void ssl_free_dh(void) {
9365 if (local_dh_1024) {
9366 DH_free(local_dh_1024);
9367 local_dh_1024 = NULL;
9368 }
9369 if (local_dh_2048) {
9370 DH_free(local_dh_2048);
9371 local_dh_2048 = NULL;
9372 }
9373 if (local_dh_4096) {
9374 DH_free(local_dh_4096);
9375 local_dh_4096 = NULL;
9376 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009377 if (global_dh) {
9378 DH_free(global_dh);
9379 global_dh = NULL;
9380 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009381}
9382#endif
9383
9384__attribute__((destructor))
9385static void __ssl_sock_deinit(void)
9386{
9387#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009388 if (ssl_ctx_lru_tree) {
9389 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009390 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009391 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009392#endif
9393
9394 ERR_remove_state(0);
9395 ERR_free_strings();
9396
9397 EVP_cleanup();
9398
9399#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9400 CRYPTO_cleanup_all_ex_data();
9401#endif
9402}
9403
9404
Emeric Brun46591952012-05-18 15:47:34 +02009405/*
9406 * Local variables:
9407 * c-indent-level: 8
9408 * c-basic-offset: 8
9409 * End:
9410 */