blob: 5dbd6b6d3e554bca5c7c59ab2473b54eb49b3b99 [file] [log] [blame]
yanbzhu08ce6ab2015-12-02 13:01:29 -05001
Emeric Brun46591952012-05-18 15:47:34 +02002/*
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02003 * SSL/TLS transport layer over SOCK_STREAM sockets
Emeric Brun46591952012-05-18 15:47:34 +02004 *
5 * Copyright (C) 2012 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
Willy Tarreau69845df2012-09-10 09:43:09 +020012 * Acknowledgement:
13 * We'd like to specially thank the Stud project authors for a very clean
14 * and well documented code which helped us understand how the OpenSSL API
15 * ought to be used in non-blocking mode. This is one difficult part which
16 * is not easy to get from the OpenSSL doc, and reading the Stud code made
17 * it much more obvious than the examples in the OpenSSL package. Keep up
18 * the good works, guys !
19 *
20 * Stud is an extremely efficient and scalable SSL/TLS proxy which combines
21 * particularly well with haproxy. For more info about this project, visit :
22 * https://github.com/bumptech/stud
23 *
Emeric Brun46591952012-05-18 15:47:34 +020024 */
25
26#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020027#include <ctype.h>
28#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020029#include <errno.h>
30#include <fcntl.h>
31#include <stdio.h>
32#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020033#include <string.h>
34#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020035
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020039#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020040#include <netinet/tcp.h>
41
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020042#include <openssl/crypto.h>
Emeric Brun46591952012-05-18 15:47:34 +020043#include <openssl/ssl.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020044#include <openssl/x509.h>
45#include <openssl/x509v3.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020046#include <openssl/err.h>
Thierry Fournier383085f2013-01-24 14:15:43 +010047#include <openssl/rand.h>
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +020048#include <openssl/hmac.h>
Lukas Tribuse4e30f72014-12-09 16:32:51 +010049#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +020050#include <openssl/ocsp.h>
51#endif
Remi Gacogne4f902b82015-05-28 16:23:00 +020052#ifndef OPENSSL_NO_DH
53#include <openssl/dh.h>
54#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020055#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000056#include <openssl/engine.h>
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020057#endif
Emeric Brun46591952012-05-18 15:47:34 +020058
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +020059#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000060#include <openssl/async.h>
61#endif
62
Christopher Faulet31af49d2015-06-09 17:29:50 +020063#include <import/lru.h>
64#include <import/xxhash.h>
65
Emeric Brun46591952012-05-18 15:47:34 +020066#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020067#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020068#include <common/compat.h>
69#include <common/config.h>
70#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020071#include <common/errors.h>
Emeric Brun46591952012-05-18 15:47:34 +020072#include <common/standard.h>
73#include <common/ticks.h>
74#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010075#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010076#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020077
Emeric Brunfc0421f2012-09-07 17:30:07 +020078#include <ebsttree.h>
79
William Lallemand32af2032016-10-29 18:09:35 +020080#include <types/applet.h>
81#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#include <types/global.h>
83#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020084#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085
Willy Tarreau7875d092012-09-10 08:20:03 +020086#include <proto/acl.h>
87#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020088#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020089#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020090#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020091#include <proto/fd.h>
92#include <proto/freq_ctr.h>
93#include <proto/frontend.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020094#include <proto/listener.h>
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +020095#include <proto/openssl-compat.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010096#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020097#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020098#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020099#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +0200100#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +0200101#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +0200102#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +0200103#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +0200104#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +0200105#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +0200106#include <proto/task.h>
107
Willy Tarreau518cedd2014-02-17 15:43:01 +0100108/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200109#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100110#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100111#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200112#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
113
Emeric Brunf282a812012-09-21 15:27:54 +0200114/* bits 0xFFFF0000 are reserved to store verify errors */
115
116/* Verify errors macros */
117#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
118#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
119#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
120
121#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
122#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
123#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200124
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100125/* Supported hash function for TLS tickets */
126#ifdef OPENSSL_NO_SHA256
127#define HASH_FUNCT EVP_sha1
128#else
129#define HASH_FUNCT EVP_sha256
130#endif /* OPENSSL_NO_SHA256 */
131
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200132/* ssl_methods flags for ssl options */
133#define MC_SSL_O_ALL 0x0000
134#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
135#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
136#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
137#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200138#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200139
140/* ssl_methods versions */
141enum {
142 CONF_TLSV_NONE = 0,
143 CONF_TLSV_MIN = 1,
144 CONF_SSLV3 = 1,
145 CONF_TLSV10 = 2,
146 CONF_TLSV11 = 3,
147 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200148 CONF_TLSV13 = 5,
149 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200150};
151
Emeric Brun850efd52014-01-29 12:24:34 +0100152/* server and bind verify method, it uses a global value as default */
153enum {
154 SSL_SOCK_VERIFY_DEFAULT = 0,
155 SSL_SOCK_VERIFY_REQUIRED = 1,
156 SSL_SOCK_VERIFY_OPTIONAL = 2,
157 SSL_SOCK_VERIFY_NONE = 3,
158};
159
William Lallemand3f85c9a2017-10-09 16:30:50 +0200160
Willy Tarreau71b734c2014-01-28 15:19:44 +0100161int sslconns = 0;
162int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100163static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100164int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200165
Willy Tarreauef934602016-12-22 23:12:01 +0100166static struct {
167 char *crt_base; /* base directory path for certificates */
168 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000169 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100170
171 char *listen_default_ciphers;
172 char *connect_default_ciphers;
173 int listen_default_ssloptions;
174 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200175 struct tls_version_filter listen_default_sslmethods;
176 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100177
178 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
179 unsigned int life_time; /* SSL session lifetime in seconds */
180 unsigned int max_record; /* SSL max record size */
181 unsigned int default_dh_param; /* SSL maximum DH parameter size */
182 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100183 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100184} global_ssl = {
185#ifdef LISTEN_DEFAULT_CIPHERS
186 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
187#endif
188#ifdef CONNECT_DEFAULT_CIPHERS
189 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
190#endif
191 .listen_default_ssloptions = BC_SSL_O_NONE,
192 .connect_default_ssloptions = SRV_SSL_O_NONE,
193
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200194 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
195 .listen_default_sslmethods.min = CONF_TLSV_NONE,
196 .listen_default_sslmethods.max = CONF_TLSV_NONE,
197 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
198 .connect_default_sslmethods.min = CONF_TLSV_NONE,
199 .connect_default_sslmethods.max = CONF_TLSV_NONE,
200
Willy Tarreauef934602016-12-22 23:12:01 +0100201#ifdef DEFAULT_SSL_MAX_RECORD
202 .max_record = DEFAULT_SSL_MAX_RECORD,
203#endif
204 .default_dh_param = SSL_DEFAULT_DH_PARAM,
205 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100206 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100207};
208
Emeric Brun821bb9b2017-06-15 16:37:39 +0200209#ifdef USE_THREAD
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100210
Emeric Brun821bb9b2017-06-15 16:37:39 +0200211static HA_RWLOCK_T *ssl_rwlocks;
212
213
214unsigned long ssl_id_function(void)
215{
216 return (unsigned long)tid;
217}
218
219void ssl_locking_function(int mode, int n, const char * file, int line)
220{
221 if (mode & CRYPTO_LOCK) {
222 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100223 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200224 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100225 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200226 }
227 else {
228 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100229 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200230 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100231 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200232 }
233}
234
235static int ssl_locking_init(void)
236{
237 int i;
238
239 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
240 if (!ssl_rwlocks)
241 return -1;
242
243 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100244 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200245
246 CRYPTO_set_id_callback(ssl_id_function);
247 CRYPTO_set_locking_callback(ssl_locking_function);
248
249 return 0;
250}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100251
Emeric Brun821bb9b2017-06-15 16:37:39 +0200252#endif
253
254
255
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100256/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100257struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100258 unsigned long long int xxh64;
259 unsigned char ciphersuite_len;
260 char ciphersuite[0];
261};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100262struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100263static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200264static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100265
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100266static int ssl_pkey_info_index = -1;
267
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200268#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
269struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
270#endif
271
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200272#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000273static unsigned int openssl_engines_initialized;
274struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
275struct ssl_engine_list {
276 struct list list;
277 ENGINE *e;
278};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200279#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000280
Remi Gacogne8de54152014-07-15 11:36:40 +0200281#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200282static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200283static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200284static DH *local_dh_1024 = NULL;
285static DH *local_dh_2048 = NULL;
286static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100287static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200288#endif /* OPENSSL_NO_DH */
289
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100290#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200291/* X509V3 Extensions that will be added on generated certificates */
292#define X509V3_EXT_SIZE 5
293static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
294 "basicConstraints",
295 "nsComment",
296 "subjectKeyIdentifier",
297 "authorityKeyIdentifier",
298 "keyUsage",
299};
300static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
301 "CA:FALSE",
302 "\"OpenSSL Generated Certificate\"",
303 "hash",
304 "keyid,issuer:always",
305 "nonRepudiation,digitalSignature,keyEncipherment"
306};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200307/* LRU cache to store generated certificate */
308static struct lru64_head *ssl_ctx_lru_tree = NULL;
309static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200310static unsigned int ssl_ctx_serial;
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100311__decl_hathreads(static HA_RWLOCK_T ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200312
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200313#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
314
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100315static struct ssl_bind_kw ssl_bind_kws[];
316
yanbzhube2774d2015-12-10 15:07:30 -0500317#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
318/* The order here matters for picking a default context,
319 * keep the most common keytype at the bottom of the list
320 */
321const char *SSL_SOCK_KEYTYPE_NAMES[] = {
322 "dsa",
323 "ecdsa",
324 "rsa"
325};
326#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100327#else
328#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500329#endif
330
William Lallemandc3cd35f2017-11-28 11:04:43 +0100331static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100332static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
333
334#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
335
336#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
337 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
338
339#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
340 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200341
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100342/*
343 * This function gives the detail of the SSL error. It is used only
344 * if the debug mode and the verbose mode are activated. It dump all
345 * the SSL error until the stack was empty.
346 */
347static forceinline void ssl_sock_dump_errors(struct connection *conn)
348{
349 unsigned long ret;
350
351 if (unlikely(global.mode & MODE_DEBUG)) {
352 while(1) {
353 ret = ERR_get_error();
354 if (ret == 0)
355 return;
356 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200357 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100358 ERR_func_error_string(ret), ERR_reason_error_string(ret));
359 }
360 }
361}
362
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200363#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500364/*
365 * struct alignment works here such that the key.key is the same as key_data
366 * Do not change the placement of key_data
367 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200368struct certificate_ocsp {
369 struct ebmb_node key;
370 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200371 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200372 long expire;
373};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200374
yanbzhube2774d2015-12-10 15:07:30 -0500375struct ocsp_cbk_arg {
376 int is_single;
377 int single_kt;
378 union {
379 struct certificate_ocsp *s_ocsp;
380 /*
381 * m_ocsp will have multiple entries dependent on key type
382 * Entry 0 - DSA
383 * Entry 1 - ECDSA
384 * Entry 2 - RSA
385 */
386 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
387 };
388};
389
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200390#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000391static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
392{
393 int err_code = ERR_ABORT;
394 ENGINE *engine;
395 struct ssl_engine_list *el;
396
397 /* grab the structural reference to the engine */
398 engine = ENGINE_by_id(engine_id);
399 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100400 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000401 goto fail_get;
402 }
403
404 if (!ENGINE_init(engine)) {
405 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100406 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000407 goto fail_init;
408 }
409
410 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100411 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000412 goto fail_set_method;
413 }
414
415 el = calloc(1, sizeof(*el));
416 el->e = engine;
417 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100418 nb_engines++;
419 if (global_ssl.async)
420 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000421 return 0;
422
423fail_set_method:
424 /* release the functional reference from ENGINE_init() */
425 ENGINE_finish(engine);
426
427fail_init:
428 /* release the structural reference from ENGINE_by_id() */
429 ENGINE_free(engine);
430
431fail_get:
432 return err_code;
433}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200434#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000435
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +0200436#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200437/*
438 * openssl async fd handler
439 */
440static void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000441{
442 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000443
Emeric Brun3854e012017-05-17 20:42:48 +0200444 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000445 * to poll this fd until it is requested
446 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000447 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000448 fd_cant_recv(fd);
449
450 /* crypto engine is available, let's notify the associated
451 * connection that it can pursue its processing.
452 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000453 __conn_sock_want_recv(conn);
454 __conn_sock_want_send(conn);
455 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000456}
457
Emeric Brun3854e012017-05-17 20:42:48 +0200458/*
459 * openssl async delayed SSL_free handler
460 */
461static void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000462{
463 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200464 OSSL_ASYNC_FD all_fd[32];
465 size_t num_all_fds = 0;
466 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000467
Emeric Brun3854e012017-05-17 20:42:48 +0200468 /* We suppose that the async job for a same SSL *
469 * are serialized. So if we are awake it is
470 * because the running job has just finished
471 * and we can remove all async fds safely
472 */
473 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
474 if (num_all_fds > 32) {
475 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
476 return;
477 }
478
479 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
480 for (i=0 ; i < num_all_fds ; i++)
481 fd_remove(all_fd[i]);
482
483 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000484 SSL_free(ssl);
485 sslconns--;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +0200486 HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000487}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000488/*
Emeric Brun3854e012017-05-17 20:42:48 +0200489 * function used to manage a returned SSL_ERROR_WANT_ASYNC
490 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000491 */
Emeric Brun3854e012017-05-17 20:42:48 +0200492static void inline ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000493{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100494 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200495 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000496 size_t num_add_fds = 0;
497 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200498 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000499
500 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
501 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200502 if (num_add_fds > 32 || num_del_fds > 32) {
503 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 +0000504 return;
505 }
506
Emeric Brun3854e012017-05-17 20:42:48 +0200507 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000508
Emeric Brun3854e012017-05-17 20:42:48 +0200509 /* We remove unused fds from the fdtab */
510 for (i=0 ; i < num_del_fds ; i++)
511 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000512
Emeric Brun3854e012017-05-17 20:42:48 +0200513 /* We add new fds to the fdtab */
514 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100515 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000516 }
517
Emeric Brun3854e012017-05-17 20:42:48 +0200518 num_add_fds = 0;
519 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
520 if (num_add_fds > 32) {
521 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
522 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000523 }
Emeric Brun3854e012017-05-17 20:42:48 +0200524
525 /* We activate the polling for all known async fds */
526 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000527 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200528 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000529 /* To ensure that the fd cache won't be used
530 * We'll prefer to catch a real RD event
531 * because handling an EAGAIN on this fd will
532 * result in a context switch and also
533 * some engines uses a fd in blocking mode.
534 */
535 fd_cant_recv(add_fd[i]);
536 }
Emeric Brun3854e012017-05-17 20:42:48 +0200537
538 /* We must also prevent the conn_handler
539 * to be called until a read event was
540 * polled on an async fd
541 */
542 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000543}
544#endif
545
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200546/*
547 * This function returns the number of seconds elapsed
548 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
549 * date presented un ASN1_GENERALIZEDTIME.
550 *
551 * In parsing error case, it returns -1.
552 */
553static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
554{
555 long epoch;
556 char *p, *end;
557 const unsigned short month_offset[12] = {
558 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
559 };
560 int year, month;
561
562 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
563
564 p = (char *)d->data;
565 end = p + d->length;
566
567 if (end - p < 4) return -1;
568 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
569 p += 4;
570 if (end - p < 2) return -1;
571 month = 10 * (p[0] - '0') + p[1] - '0';
572 if (month < 1 || month > 12) return -1;
573 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
574 We consider leap years and the current month (<marsh or not) */
575 epoch = ( ((year - 1970) * 365)
576 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
577 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
578 + month_offset[month-1]
579 ) * 24 * 60 * 60;
580 p += 2;
581 if (end - p < 2) return -1;
582 /* Add the number of seconds of completed days of current month */
583 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
584 p += 2;
585 if (end - p < 2) return -1;
586 /* Add the completed hours of the current day */
587 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
588 p += 2;
589 if (end - p < 2) return -1;
590 /* Add the completed minutes of the current hour */
591 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
592 p += 2;
593 if (p == end) return -1;
594 /* Test if there is available seconds */
595 if (p[0] < '0' || p[0] > '9')
596 goto nosec;
597 if (end - p < 2) return -1;
598 /* Add the seconds of the current minute */
599 epoch += 10 * (p[0] - '0') + p[1] - '0';
600 p += 2;
601 if (p == end) return -1;
602 /* Ignore seconds float part if present */
603 if (p[0] == '.') {
604 do {
605 if (++p == end) return -1;
606 } while (p[0] >= '0' && p[0] <= '9');
607 }
608
609nosec:
610 if (p[0] == 'Z') {
611 if (end - p != 1) return -1;
612 return epoch;
613 }
614 else if (p[0] == '+') {
615 if (end - p != 5) return -1;
616 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700617 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 +0200618 }
619 else if (p[0] == '-') {
620 if (end - p != 5) return -1;
621 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700622 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 +0200623 }
624
625 return -1;
626}
627
Emeric Brun1d3865b2014-06-20 15:37:32 +0200628static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200629
630/* This function starts to check if the OCSP response (in DER format) contained
631 * in chunk 'ocsp_response' is valid (else exits on error).
632 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
633 * contained in the OCSP Response and exits on error if no match.
634 * If it's a valid OCSP Response:
635 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
636 * pointed by 'ocsp'.
637 * If 'ocsp' is NULL, the function looks up into the OCSP response's
638 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
639 * from the response) and exits on error if not found. Finally, If an OCSP response is
640 * already present in the container, it will be overwritten.
641 *
642 * Note: OCSP response containing more than one OCSP Single response is not
643 * considered valid.
644 *
645 * Returns 0 on success, 1 in error case.
646 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200647static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
648 struct certificate_ocsp *ocsp,
649 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200650{
651 OCSP_RESPONSE *resp;
652 OCSP_BASICRESP *bs = NULL;
653 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200654 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200655 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200656 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200657 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200658 int reason;
659 int ret = 1;
660
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200661 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
662 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200663 if (!resp) {
664 memprintf(err, "Unable to parse OCSP response");
665 goto out;
666 }
667
668 rc = OCSP_response_status(resp);
669 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
670 memprintf(err, "OCSP response status not successful");
671 goto out;
672 }
673
674 bs = OCSP_response_get1_basic(resp);
675 if (!bs) {
676 memprintf(err, "Failed to get basic response from OCSP Response");
677 goto out;
678 }
679
680 count_sr = OCSP_resp_count(bs);
681 if (count_sr > 1) {
682 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
683 goto out;
684 }
685
686 sr = OCSP_resp_get0(bs, 0);
687 if (!sr) {
688 memprintf(err, "Failed to get OCSP single response");
689 goto out;
690 }
691
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200692 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
693
Emeric Brun4147b2e2014-06-16 18:36:30 +0200694 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200695 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200696 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200697 goto out;
698 }
699
Emeric Brun13a6b482014-06-20 15:44:34 +0200700 if (!nextupd) {
701 memprintf(err, "OCSP single response: missing nextupdate");
702 goto out;
703 }
704
Emeric Brunc8b27b62014-06-19 14:16:17 +0200705 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200706 if (!rc) {
707 memprintf(err, "OCSP single response: no longer valid.");
708 goto out;
709 }
710
711 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200712 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200713 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
714 goto out;
715 }
716 }
717
718 if (!ocsp) {
719 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
720 unsigned char *p;
721
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200722 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200723 if (!rc) {
724 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
725 goto out;
726 }
727
728 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
729 memprintf(err, "OCSP single response: Certificate ID too long");
730 goto out;
731 }
732
733 p = key;
734 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200735 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200736 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
737 if (!ocsp) {
738 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
739 goto out;
740 }
741 }
742
743 /* According to comments on "chunk_dup", the
744 previous chunk buffer will be freed */
745 if (!chunk_dup(&ocsp->response, ocsp_response)) {
746 memprintf(err, "OCSP response: Memory allocation error");
747 goto out;
748 }
749
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200750 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
751
Emeric Brun4147b2e2014-06-16 18:36:30 +0200752 ret = 0;
753out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100754 ERR_clear_error();
755
Emeric Brun4147b2e2014-06-16 18:36:30 +0200756 if (bs)
757 OCSP_BASICRESP_free(bs);
758
759 if (resp)
760 OCSP_RESPONSE_free(resp);
761
762 return ret;
763}
764/*
765 * External function use to update the OCSP response in the OCSP response's
766 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
767 * to update in DER format.
768 *
769 * Returns 0 on success, 1 in error case.
770 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200771int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200772{
773 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
774}
775
776/*
777 * This function load the OCSP Resonse in DER format contained in file at
778 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
779 *
780 * Returns 0 on success, 1 in error case.
781 */
782static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
783{
784 int fd = -1;
785 int r = 0;
786 int ret = 1;
787
788 fd = open(ocsp_path, O_RDONLY);
789 if (fd == -1) {
790 memprintf(err, "Error opening OCSP response file");
791 goto end;
792 }
793
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200794 trash.data = 0;
795 while (trash.data < trash.size) {
796 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200797 if (r < 0) {
798 if (errno == EINTR)
799 continue;
800
801 memprintf(err, "Error reading OCSP response from file");
802 goto end;
803 }
804 else if (r == 0) {
805 break;
806 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200807 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200808 }
809
810 close(fd);
811 fd = -1;
812
813 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
814end:
815 if (fd != -1)
816 close(fd);
817
818 return ret;
819}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100820#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200821
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100822#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
823static 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)
824{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100825 struct tls_keys_ref *ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100826 struct tls_sess_key *keys;
827 struct connection *conn;
828 int head;
829 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100830 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100831
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200832 conn = SSL_get_ex_data(s, ssl_app_data_index);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100833 ref = objt_listener(conn->target)->bind_conf->keys_ref;
834 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
835
836 keys = ref->tlskeys;
837 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100838
839 if (enc) {
840 memcpy(key_name, keys[head].name, 16);
841
842 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100843 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100844
845 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].aes_key, iv))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100846 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100847
848 HMAC_Init_ex(hctx, keys[head].hmac_key, 16, HASH_FUNCT(), NULL);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100849 ret = 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100850 } else {
851 for (i = 0; i < TLS_TICKETS_NO; i++) {
852 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
853 goto found;
854 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100855 ret = 0;
856 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100857
Christopher Faulet16f45c82018-02-16 11:23:49 +0100858 found:
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100859 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].hmac_key, 16, HASH_FUNCT(), NULL);
860 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 +0100861 goto end;
862
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100863 /* 2 for key renewal, 1 if current key is still valid */
Christopher Faulet16f45c82018-02-16 11:23:49 +0100864 ret = i ? 2 : 1;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100865 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100866 end:
867 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
868 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200869}
870
871struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
872{
873 struct tls_keys_ref *ref;
874
875 list_for_each_entry(ref, &tlskeys_reference, list)
876 if (ref->filename && strcmp(filename, ref->filename) == 0)
877 return ref;
878 return NULL;
879}
880
881struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
882{
883 struct tls_keys_ref *ref;
884
885 list_for_each_entry(ref, &tlskeys_reference, list)
886 if (ref->unique_id == unique_id)
887 return ref;
888 return NULL;
889}
890
Willy Tarreau83061a82018-07-13 11:56:34 +0200891void ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
892 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100893{
894 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200895 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
896 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +0100897 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
898 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
899}
900
Willy Tarreau83061a82018-07-13 11:56:34 +0200901int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +0100902{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200903 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
904
905 if(!ref) {
906 memprintf(err, "Unable to locate the referenced filename: %s", filename);
907 return 1;
908 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100909 ssl_sock_update_tlskey_ref(ref, tlskey);
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200910 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100911}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200912
913/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +0100914 * automatic ids. It's called just after the basic checks. It returns
915 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200916 */
Willy Tarreaud1c57502016-12-22 22:46:15 +0100917static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200918{
919 int i = 0;
920 struct tls_keys_ref *ref, *ref2, *ref3;
921 struct list tkr = LIST_HEAD_INIT(tkr);
922
923 list_for_each_entry(ref, &tlskeys_reference, list) {
924 if (ref->unique_id == -1) {
925 /* Look for the first free id. */
926 while (1) {
927 list_for_each_entry(ref2, &tlskeys_reference, list) {
928 if (ref2->unique_id == i) {
929 i++;
930 break;
931 }
932 }
933 if (&ref2->list == &tlskeys_reference)
934 break;
935 }
936
937 /* Uses the unique id and increment it for the next entry. */
938 ref->unique_id = i;
939 i++;
940 }
941 }
942
943 /* This sort the reference list by id. */
944 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
945 LIST_DEL(&ref->list);
946 list_for_each_entry(ref3, &tkr, list) {
947 if (ref->unique_id < ref3->unique_id) {
948 LIST_ADDQ(&ref3->list, &ref->list);
949 break;
950 }
951 }
952 if (&ref3->list == &tkr)
953 LIST_ADDQ(&tkr, &ref->list);
954 }
955
956 /* swap root */
957 LIST_ADD(&tkr, &tlskeys_reference);
958 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +0100959 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200960}
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100961#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
962
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100963#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -0500964int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
965{
966 switch (evp_keytype) {
967 case EVP_PKEY_RSA:
968 return 2;
969 case EVP_PKEY_DSA:
970 return 0;
971 case EVP_PKEY_EC:
972 return 1;
973 }
974
975 return -1;
976}
977
Emeric Brun4147b2e2014-06-16 18:36:30 +0200978/*
979 * Callback used to set OCSP status extension content in server hello.
980 */
981int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
982{
yanbzhube2774d2015-12-10 15:07:30 -0500983 struct certificate_ocsp *ocsp;
984 struct ocsp_cbk_arg *ocsp_arg;
985 char *ssl_buf;
986 EVP_PKEY *ssl_pkey;
987 int key_type;
988 int index;
989
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200990 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -0500991
992 ssl_pkey = SSL_get_privatekey(ssl);
993 if (!ssl_pkey)
994 return SSL_TLSEXT_ERR_NOACK;
995
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200996 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -0500997
998 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
999 ocsp = ocsp_arg->s_ocsp;
1000 else {
1001 /* For multiple certs per context, we have to find the correct OCSP response based on
1002 * the certificate type
1003 */
1004 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1005
1006 if (index < 0)
1007 return SSL_TLSEXT_ERR_NOACK;
1008
1009 ocsp = ocsp_arg->m_ocsp[index];
1010
1011 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001012
1013 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001014 !ocsp->response.area ||
1015 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001016 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001017 return SSL_TLSEXT_ERR_NOACK;
1018
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001019 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001020 if (!ssl_buf)
1021 return SSL_TLSEXT_ERR_NOACK;
1022
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001023 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1024 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001025
1026 return SSL_TLSEXT_ERR_OK;
1027}
1028
1029/*
1030 * This function enables the handling of OCSP status extension on 'ctx' if a
1031 * file name 'cert_path' suffixed using ".ocsp" is present.
1032 * To enable OCSP status extension, the issuer's certificate is mandatory.
1033 * It should be present in the certificate's extra chain builded from file
1034 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1035 * named 'cert_path' suffixed using '.issuer'.
1036 *
1037 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1038 * response. If file is empty or content is not a valid OCSP response,
1039 * OCSP status extension is enabled but OCSP response is ignored (a warning
1040 * is displayed).
1041 *
1042 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
1043 * succesfully enabled, or -1 in other error case.
1044 */
1045static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1046{
1047
1048 BIO *in = NULL;
1049 X509 *x, *xi = NULL, *issuer = NULL;
1050 STACK_OF(X509) *chain = NULL;
1051 OCSP_CERTID *cid = NULL;
1052 SSL *ssl;
1053 char ocsp_path[MAXPATHLEN+1];
1054 int i, ret = -1;
1055 struct stat st;
1056 struct certificate_ocsp *ocsp = NULL, *iocsp;
1057 char *warn = NULL;
1058 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001059 pem_password_cb *passwd_cb;
1060 void *passwd_cb_userdata;
1061 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001062
1063 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1064
1065 if (stat(ocsp_path, &st))
1066 return 1;
1067
1068 ssl = SSL_new(ctx);
1069 if (!ssl)
1070 goto out;
1071
1072 x = SSL_get_certificate(ssl);
1073 if (!x)
1074 goto out;
1075
1076 /* Try to lookup for issuer in certificate extra chain */
1077#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1078 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1079#else
1080 chain = ctx->extra_certs;
1081#endif
1082 for (i = 0; i < sk_X509_num(chain); i++) {
1083 issuer = sk_X509_value(chain, i);
1084 if (X509_check_issued(issuer, x) == X509_V_OK)
1085 break;
1086 else
1087 issuer = NULL;
1088 }
1089
1090 /* If not found try to load issuer from a suffixed file */
1091 if (!issuer) {
1092 char issuer_path[MAXPATHLEN+1];
1093
1094 in = BIO_new(BIO_s_file());
1095 if (!in)
1096 goto out;
1097
1098 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1099 if (BIO_read_filename(in, issuer_path) <= 0)
1100 goto out;
1101
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001102 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1103 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1104
1105 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001106 if (!xi)
1107 goto out;
1108
1109 if (X509_check_issued(xi, x) != X509_V_OK)
1110 goto out;
1111
1112 issuer = xi;
1113 }
1114
1115 cid = OCSP_cert_to_id(0, x, issuer);
1116 if (!cid)
1117 goto out;
1118
1119 i = i2d_OCSP_CERTID(cid, NULL);
1120 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1121 goto out;
1122
Vincent Bernat02779b62016-04-03 13:48:43 +02001123 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001124 if (!ocsp)
1125 goto out;
1126
1127 p = ocsp->key_data;
1128 i2d_OCSP_CERTID(cid, &p);
1129
1130 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1131 if (iocsp == ocsp)
1132 ocsp = NULL;
1133
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001134#ifndef SSL_CTX_get_tlsext_status_cb
1135# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1136 *cb = (void (*) (void))ctx->tlsext_status_cb;
1137#endif
1138 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1139
1140 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001141 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001142 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001143
1144 cb_arg->is_single = 1;
1145 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001146
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001147 pkey = X509_get_pubkey(x);
1148 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1149 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001150
1151 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1152 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1153 } else {
1154 /*
1155 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1156 * Update that cb_arg with the new cert's staple
1157 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001158 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001159 struct certificate_ocsp *tmp_ocsp;
1160 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001161 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001162 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001163
1164#ifdef SSL_CTX_get_tlsext_status_arg
1165 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1166#else
1167 cb_arg = ctx->tlsext_status_arg;
1168#endif
yanbzhube2774d2015-12-10 15:07:30 -05001169
1170 /*
1171 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1172 * the order of operations below matter, take care when changing it
1173 */
1174 tmp_ocsp = cb_arg->s_ocsp;
1175 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1176 cb_arg->s_ocsp = NULL;
1177 cb_arg->m_ocsp[index] = tmp_ocsp;
1178 cb_arg->is_single = 0;
1179 cb_arg->single_kt = 0;
1180
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001181 pkey = X509_get_pubkey(x);
1182 key_type = EVP_PKEY_base_id(pkey);
1183 EVP_PKEY_free(pkey);
1184
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001185 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001186 if (index >= 0 && !cb_arg->m_ocsp[index])
1187 cb_arg->m_ocsp[index] = iocsp;
1188
1189 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001190
1191 ret = 0;
1192
1193 warn = NULL;
1194 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1195 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001196 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001197 }
1198
1199out:
1200 if (ssl)
1201 SSL_free(ssl);
1202
1203 if (in)
1204 BIO_free(in);
1205
1206 if (xi)
1207 X509_free(xi);
1208
1209 if (cid)
1210 OCSP_CERTID_free(cid);
1211
1212 if (ocsp)
1213 free(ocsp);
1214
1215 if (warn)
1216 free(warn);
1217
1218
1219 return ret;
1220}
1221
1222#endif
1223
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001224#ifdef OPENSSL_IS_BORINGSSL
1225static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1226{
1227 char ocsp_path[MAXPATHLEN+1];
1228 struct stat st;
1229 int fd = -1, r = 0;
1230
1231 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1232 if (stat(ocsp_path, &st))
1233 return 0;
1234
1235 fd = open(ocsp_path, O_RDONLY);
1236 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001237 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001238 return -1;
1239 }
1240
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001241 trash.data = 0;
1242 while (trash.data < trash.size) {
1243 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001244 if (r < 0) {
1245 if (errno == EINTR)
1246 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001247 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001248 close(fd);
1249 return -1;
1250 }
1251 else if (r == 0) {
1252 break;
1253 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001254 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001255 }
1256 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001257 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1258 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001259}
1260#endif
1261
Daniel Jakots54ffb912015-11-06 20:02:41 +01001262#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001263
1264#define CT_EXTENSION_TYPE 18
1265
1266static int sctl_ex_index = -1;
1267
1268/*
1269 * Try to parse Signed Certificate Timestamp List structure. This function
1270 * makes only basic test if the data seems like SCTL. No signature validation
1271 * is performed.
1272 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001273static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001274{
1275 int ret = 1;
1276 int len, pos, sct_len;
1277 unsigned char *data;
1278
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001279 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001280 goto out;
1281
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001282 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001283 len = (data[0] << 8) | data[1];
1284
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001285 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001286 goto out;
1287
1288 data = data + 2;
1289 pos = 0;
1290 while (pos < len) {
1291 if (len - pos < 2)
1292 goto out;
1293
1294 sct_len = (data[pos] << 8) | data[pos + 1];
1295 if (pos + sct_len + 2 > len)
1296 goto out;
1297
1298 pos += sct_len + 2;
1299 }
1300
1301 ret = 0;
1302
1303out:
1304 return ret;
1305}
1306
Willy Tarreau83061a82018-07-13 11:56:34 +02001307static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1308 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001309{
1310 int fd = -1;
1311 int r = 0;
1312 int ret = 1;
1313
1314 *sctl = NULL;
1315
1316 fd = open(sctl_path, O_RDONLY);
1317 if (fd == -1)
1318 goto end;
1319
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001320 trash.data = 0;
1321 while (trash.data < trash.size) {
1322 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001323 if (r < 0) {
1324 if (errno == EINTR)
1325 continue;
1326
1327 goto end;
1328 }
1329 else if (r == 0) {
1330 break;
1331 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001332 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001333 }
1334
1335 ret = ssl_sock_parse_sctl(&trash);
1336 if (ret)
1337 goto end;
1338
Vincent Bernat02779b62016-04-03 13:48:43 +02001339 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001340 if (!chunk_dup(*sctl, &trash)) {
1341 free(*sctl);
1342 *sctl = NULL;
1343 goto end;
1344 }
1345
1346end:
1347 if (fd != -1)
1348 close(fd);
1349
1350 return ret;
1351}
1352
1353int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1354{
Willy Tarreau83061a82018-07-13 11:56:34 +02001355 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001356
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001357 *out = (unsigned char *) sctl->area;
1358 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001359
1360 return 1;
1361}
1362
1363int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1364{
1365 return 1;
1366}
1367
1368static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1369{
1370 char sctl_path[MAXPATHLEN+1];
1371 int ret = -1;
1372 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001373 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001374
1375 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1376
1377 if (stat(sctl_path, &st))
1378 return 1;
1379
1380 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1381 goto out;
1382
1383 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1384 free(sctl);
1385 goto out;
1386 }
1387
1388 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1389
1390 ret = 0;
1391
1392out:
1393 return ret;
1394}
1395
1396#endif
1397
Emeric Brune1f38db2012-09-03 20:36:47 +02001398void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1399{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001400 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brund8b2bb52014-01-28 15:43:53 +01001401 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001402 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001403
1404 if (where & SSL_CB_HANDSHAKE_START) {
1405 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001406 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 +02001407 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001408 conn->err_code = CO_ER_SSL_RENEG;
1409 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001410 }
Emeric Brund8b2bb52014-01-28 15:43:53 +01001411
1412 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
1413 if (!(conn->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
1414 /* Long certificate chains optimz
1415 If write and read bios are differents, we
1416 consider that the buffering was activated,
1417 so we rise the output buffer size from 4k
1418 to 16k */
1419 write_bio = SSL_get_wbio(ssl);
1420 if (write_bio != SSL_get_rbio(ssl)) {
1421 BIO_set_write_buffer_size(write_bio, 16384);
1422 conn->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
1423 }
1424 }
1425 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001426}
1427
Emeric Brune64aef12012-09-21 13:15:06 +02001428/* Callback is called for each certificate of the chain during a verify
1429 ok is set to 1 if preverify detect no error on current certificate.
1430 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001431int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001432{
1433 SSL *ssl;
1434 struct connection *conn;
Emeric Brun81c00f02012-09-21 14:31:21 +02001435 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001436
1437 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001438 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001439
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001440 conn->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001441
Emeric Brun81c00f02012-09-21 14:31:21 +02001442 if (ok) /* no errors */
1443 return ok;
1444
1445 depth = X509_STORE_CTX_get_error_depth(x_store);
1446 err = X509_STORE_CTX_get_error(x_store);
1447
1448 /* check if CA error needs to be ignored */
1449 if (depth > 0) {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001450 if (!SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st)) {
1451 conn->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1452 conn->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001453 }
1454
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001455 if (objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001456 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001457 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001458 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001459 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001460
Willy Tarreau20879a02012-12-03 16:32:10 +01001461 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001462 return 0;
1463 }
1464
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001465 if (!SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st))
1466 conn->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001467
Emeric Brun81c00f02012-09-21 14:31:21 +02001468 /* check if certificate error needs to be ignored */
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001469 if (objt_listener(conn->target)->bind_conf->crt_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_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001476 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001477}
1478
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001479static inline
1480void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001481 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001482{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001483 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001484 unsigned char *msg;
1485 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001486 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001487
1488 /* This function is called for "from client" and "to server"
1489 * connections. The combination of write_p == 0 and content_type == 22
1490 * is only avalaible during "from client" connection.
1491 */
1492
1493 /* "write_p" is set to 0 is the bytes are received messages,
1494 * otherwise it is set to 1.
1495 */
1496 if (write_p != 0)
1497 return;
1498
1499 /* content_type contains the type of message received or sent
1500 * according with the SSL/TLS protocol spec. This message is
1501 * encoded with one byte. The value 256 (two bytes) is used
1502 * for designing the SSL/TLS record layer. According with the
1503 * rfc6101, the expected message (other than 256) are:
1504 * - change_cipher_spec(20)
1505 * - alert(21)
1506 * - handshake(22)
1507 * - application_data(23)
1508 * - (255)
1509 * We are interessed by the handshake and specially the client
1510 * hello.
1511 */
1512 if (content_type != 22)
1513 return;
1514
1515 /* The message length is at least 4 bytes, containing the
1516 * message type and the message length.
1517 */
1518 if (len < 4)
1519 return;
1520
1521 /* First byte of the handshake message id the type of
1522 * message. The konwn types are:
1523 * - hello_request(0)
1524 * - client_hello(1)
1525 * - server_hello(2)
1526 * - certificate(11)
1527 * - server_key_exchange (12)
1528 * - certificate_request(13)
1529 * - server_hello_done(14)
1530 * We are interested by the client hello.
1531 */
1532 msg = (unsigned char *)buf;
1533 if (msg[0] != 1)
1534 return;
1535
1536 /* Next three bytes are the length of the message. The total length
1537 * must be this decoded length + 4. If the length given as argument
1538 * is not the same, we abort the protocol dissector.
1539 */
1540 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1541 if (len < rec_len + 4)
1542 return;
1543 msg += 4;
1544 end = msg + rec_len;
1545 if (end < msg)
1546 return;
1547
1548 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1549 * for minor, the random, composed by 4 bytes for the unix time and
1550 * 28 bytes for unix payload, and them 1 byte for the session id. So
1551 * we jump 1 + 1 + 4 + 28 + 1 bytes.
1552 */
1553 msg += 1 + 1 + 4 + 28 + 1;
1554 if (msg > end)
1555 return;
1556
1557 /* Next two bytes are the ciphersuite length. */
1558 if (msg + 2 > end)
1559 return;
1560 rec_len = (msg[0] << 8) + msg[1];
1561 msg += 2;
1562 if (msg + rec_len > end || msg + rec_len < msg)
1563 return;
1564
Willy Tarreaubafbe012017-11-24 17:34:44 +01001565 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001566 if (!capture)
1567 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001568 /* Compute the xxh64 of the ciphersuite. */
1569 capture->xxh64 = XXH64(msg, rec_len, 0);
1570
1571 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001572 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1573 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001574 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001575
1576 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001577}
1578
Emeric Brun29f037d2014-04-25 19:05:36 +02001579/* Callback is called for ssl protocol analyse */
1580void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1581{
Emeric Brun29f037d2014-04-25 19:05:36 +02001582#ifdef TLS1_RT_HEARTBEAT
1583 /* test heartbeat received (write_p is set to 0
1584 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001585 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001586 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreauf51c6982014-04-25 20:02:39 +02001587 const unsigned char *p = buf;
1588 unsigned int payload;
1589
Emeric Brun29f037d2014-04-25 19:05:36 +02001590 conn->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001591
1592 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1593 if (*p != TLS1_HB_REQUEST)
1594 return;
1595
Willy Tarreauaeed6722014-04-25 23:59:58 +02001596 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001597 goto kill_it;
1598
1599 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001600 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001601 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001602 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001603 /* We have a clear heartbleed attack (CVE-2014-0160), the
1604 * advertised payload is larger than the advertised packet
1605 * length, so we have garbage in the buffer between the
1606 * payload and the end of the buffer (p+len). We can't know
1607 * if the SSL stack is patched, and we don't know if we can
1608 * safely wipe out the area between p+3+len and payload.
1609 * So instead, we prevent the response from being sent by
1610 * setting the max_send_fragment to 0 and we report an SSL
1611 * error, which will kill this connection. It will be reported
1612 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001613 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1614 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001615 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001616 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1617 return;
1618 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001619#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001620 if (global_ssl.capture_cipherlist > 0)
1621 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001622}
1623
Bernard Spil13c53f82018-02-15 13:34:58 +01001624#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001625/* This callback is used so that the server advertises the list of
1626 * negociable protocols for NPN.
1627 */
1628static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1629 unsigned int *len, void *arg)
1630{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001631 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001632
1633 *data = (const unsigned char *)conf->npn_str;
1634 *len = conf->npn_len;
1635 return SSL_TLSEXT_ERR_OK;
1636}
1637#endif
1638
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001639#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001640/* This callback is used so that the server advertises the list of
1641 * negociable protocols for ALPN.
1642 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001643static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1644 unsigned char *outlen,
1645 const unsigned char *server,
1646 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001647{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001648 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001649
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001650 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1651 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1652 return SSL_TLSEXT_ERR_NOACK;
1653 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001654 return SSL_TLSEXT_ERR_OK;
1655}
1656#endif
1657
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001658#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001659#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001660
Christopher Faulet30548802015-06-11 13:39:32 +02001661/* Create a X509 certificate with the specified servername and serial. This
1662 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001663static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001664ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001665{
Christopher Faulet7969a332015-10-09 11:15:03 +02001666 X509 *cacert = bind_conf->ca_sign_cert;
1667 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001668 SSL_CTX *ssl_ctx = NULL;
1669 X509 *newcrt = NULL;
1670 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001671 SSL *tmp_ssl = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001672 X509_NAME *name;
1673 const EVP_MD *digest;
1674 X509V3_CTX ctx;
1675 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001676 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001677
Christopher Faulet48a83322017-07-28 16:56:09 +02001678 /* Get the private key of the default certificate and use it */
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001679#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
1680 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1681#else
1682 tmp_ssl = SSL_new(bind_conf->default_ctx);
1683 if (tmp_ssl)
1684 pkey = SSL_get_privatekey(tmp_ssl);
1685#endif
1686 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001687 goto mkcert_error;
1688
1689 /* Create the certificate */
1690 if (!(newcrt = X509_new()))
1691 goto mkcert_error;
1692
1693 /* Set version number for the certificate (X509v3) and the serial
1694 * number */
1695 if (X509_set_version(newcrt, 2L) != 1)
1696 goto mkcert_error;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001697 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001698
1699 /* Set duration for the certificate */
1700 if (!X509_gmtime_adj(X509_get_notBefore(newcrt), (long)-60*60*24) ||
1701 !X509_gmtime_adj(X509_get_notAfter(newcrt),(long)60*60*24*365))
1702 goto mkcert_error;
1703
1704 /* set public key in the certificate */
1705 if (X509_set_pubkey(newcrt, pkey) != 1)
1706 goto mkcert_error;
1707
1708 /* Set issuer name from the CA */
1709 if (!(name = X509_get_subject_name(cacert)))
1710 goto mkcert_error;
1711 if (X509_set_issuer_name(newcrt, name) != 1)
1712 goto mkcert_error;
1713
1714 /* Set the subject name using the same, but the CN */
1715 name = X509_NAME_dup(name);
1716 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1717 (const unsigned char *)servername,
1718 -1, -1, 0) != 1) {
1719 X509_NAME_free(name);
1720 goto mkcert_error;
1721 }
1722 if (X509_set_subject_name(newcrt, name) != 1) {
1723 X509_NAME_free(name);
1724 goto mkcert_error;
1725 }
1726 X509_NAME_free(name);
1727
1728 /* Add x509v3 extensions as specified */
1729 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1730 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1731 X509_EXTENSION *ext;
1732
1733 if (!(ext = X509V3_EXT_conf(NULL, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
1734 goto mkcert_error;
1735 if (!X509_add_ext(newcrt, ext, -1)) {
1736 X509_EXTENSION_free(ext);
1737 goto mkcert_error;
1738 }
1739 X509_EXTENSION_free(ext);
1740 }
1741
1742 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001743
1744 key_type = EVP_PKEY_base_id(capkey);
1745
1746 if (key_type == EVP_PKEY_DSA)
1747 digest = EVP_sha1();
1748 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001749 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001750 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001751 digest = EVP_sha256();
1752 else {
Christopher Faulete7db2162015-10-19 13:59:24 +02001753#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001754 int nid;
1755
1756 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1757 goto mkcert_error;
1758 if (!(digest = EVP_get_digestbynid(nid)))
1759 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001760#else
1761 goto mkcert_error;
1762#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001763 }
1764
Christopher Faulet31af49d2015-06-09 17:29:50 +02001765 if (!(X509_sign(newcrt, capkey, digest)))
1766 goto mkcert_error;
1767
1768 /* Create and set the new SSL_CTX */
1769 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1770 goto mkcert_error;
1771 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1772 goto mkcert_error;
1773 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1774 goto mkcert_error;
1775 if (!SSL_CTX_check_private_key(ssl_ctx))
1776 goto mkcert_error;
1777
1778 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001779
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001780#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001781 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001782#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001783#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1784 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001785 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001786 EC_KEY *ecc;
1787 int nid;
1788
1789 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1790 goto end;
1791 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1792 goto end;
1793 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1794 EC_KEY_free(ecc);
1795 }
1796#endif
1797 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001798 return ssl_ctx;
1799
1800 mkcert_error:
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001801 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001802 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1803 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001804 return NULL;
1805}
1806
Christopher Faulet7969a332015-10-09 11:15:03 +02001807SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001808ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001809{
1810 struct bind_conf *bind_conf = objt_listener(conn->target)->bind_conf;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001811
1812 return ssl_sock_do_create_cert(servername, bind_conf, conn->xprt_ctx);
Christopher Faulet7969a332015-10-09 11:15:03 +02001813}
1814
Christopher Faulet30548802015-06-11 13:39:32 +02001815/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001816 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001817SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001818ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001819{
1820 struct lru64 *lru = NULL;
1821
1822 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001823 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001824 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001825 if (lru && lru->domain) {
1826 if (ssl)
1827 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001828 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001829 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001830 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001831 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001832 }
1833 return NULL;
1834}
1835
Emeric Brun821bb9b2017-06-15 16:37:39 +02001836/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1837 * function is not thread-safe, it should only be used to check if a certificate
1838 * exists in the lru cache (with no warranty it will not be removed by another
1839 * thread). It is kept for backward compatibility. */
1840SSL_CTX *
1841ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1842{
1843 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1844}
1845
Christopher Fauletd2cab922015-07-28 16:03:47 +02001846/* Set a certificate int the LRU cache used to store generated
1847 * certificate. Return 0 on success, otherwise -1 */
1848int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001849ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001850{
1851 struct lru64 *lru = NULL;
1852
1853 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001854 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001855 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001856 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001857 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001858 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001859 }
Christopher Faulet30548802015-06-11 13:39:32 +02001860 if (lru->domain && lru->data)
1861 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001862 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001863 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001864 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001865 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001866 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001867}
1868
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001869/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001870unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001871ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001872{
1873 return XXH32(data, len, ssl_ctx_lru_seed);
1874}
1875
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001876/* Generate a cert and immediately assign it to the SSL session so that the cert's
1877 * refcount is maintained regardless of the cert's presence in the LRU cache.
1878 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001879static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001880ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001881{
1882 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001883 SSL_CTX *ssl_ctx = NULL;
1884 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001885 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001886
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001887 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001888 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001889 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001890 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001891 if (lru && lru->domain)
1892 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001893 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001894 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001895 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001896 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001897 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001898 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001899 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001900 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001901 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001902 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001903 SSL_set_SSL_CTX(ssl, ssl_ctx);
1904 /* No LRU cache, this CTX will be released as soon as the session dies */
1905 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001906 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001907 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001908 return 0;
1909}
1910static int
1911ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1912{
1913 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001914 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001915
1916 conn_get_to_addr(conn);
1917 if (conn->flags & CO_FL_ADDR_TO_SET) {
1918 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02001919 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001920 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001921 }
1922 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001923}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001924#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02001925
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001926
1927#ifndef SSL_OP_CIPHER_SERVER_PREFERENCE /* needs OpenSSL >= 0.9.7 */
1928#define SSL_OP_CIPHER_SERVER_PREFERENCE 0
1929#endif
1930
1931#ifndef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* needs OpenSSL >= 0.9.7 */
1932#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0
1933#define SSL_renegotiate_pending(arg) 0
1934#endif
1935#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 0.9.8 */
1936#define SSL_OP_SINGLE_ECDH_USE 0
1937#endif
1938#ifndef SSL_OP_NO_TICKET /* needs OpenSSL >= 0.9.8 */
1939#define SSL_OP_NO_TICKET 0
1940#endif
1941#ifndef SSL_OP_NO_COMPRESSION /* needs OpenSSL >= 0.9.9 */
1942#define SSL_OP_NO_COMPRESSION 0
1943#endif
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001944#ifdef OPENSSL_NO_SSL3 /* SSLv3 support removed */
1945#undef SSL_OP_NO_SSLv3
1946#define SSL_OP_NO_SSLv3 0
1947#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001948#ifndef SSL_OP_NO_TLSv1_1 /* needs OpenSSL >= 1.0.1 */
1949#define SSL_OP_NO_TLSv1_1 0
1950#endif
1951#ifndef SSL_OP_NO_TLSv1_2 /* needs OpenSSL >= 1.0.1 */
1952#define SSL_OP_NO_TLSv1_2 0
1953#endif
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02001954#ifndef SSL_OP_NO_TLSv1_3 /* needs OpenSSL >= 1.1.1 */
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001955#define SSL_OP_NO_TLSv1_3 0
1956#endif
1957#ifndef SSL_OP_SINGLE_DH_USE /* needs OpenSSL >= 0.9.6 */
1958#define SSL_OP_SINGLE_DH_USE 0
1959#endif
1960#ifndef SSL_OP_SINGLE_ECDH_USE /* needs OpenSSL >= 1.0.0 */
1961#define SSL_OP_SINGLE_ECDH_USE 0
1962#endif
1963#ifndef SSL_MODE_RELEASE_BUFFERS /* needs OpenSSL >= 1.0.0 */
1964#define SSL_MODE_RELEASE_BUFFERS 0
1965#endif
1966#ifndef SSL_MODE_SMALL_BUFFERS /* needs small_records.patch */
1967#define SSL_MODE_SMALL_BUFFERS 0
1968#endif
Lukas Tribus926594f2018-05-18 17:55:57 +02001969#ifndef SSL_OP_PRIORITIZE_CHACHA /* needs OpenSSL >= 1.1.1 */
1970#define SSL_OP_PRIORITIZE_CHACHA 0
1971#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001972
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02001973#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001974typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
1975
1976static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001977{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02001978#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001979 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001980 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
1981#endif
1982}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001983static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
1984 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001985 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
1986}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001987static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001988#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001989 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001990 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
1991#endif
1992}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001993static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001994#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02001995 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02001996 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
1997#endif
1998}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01001999/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002000static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2001/* Unusable in this context. */
2002static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2003static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2004static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2005static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2006static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002007#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002008typedef enum { SET_MIN, SET_MAX } set_context_func;
2009
2010static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2011 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2013}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2015 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2016 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2017}
2018static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2019 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2021}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002022static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2023 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2024 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2025}
2026static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2027 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002028 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2029}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002030static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2031 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2032 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2033}
2034static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2035 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002036 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2037}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002038static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2039 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2040 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2041}
2042static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002043#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002044 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002045 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2046#endif
2047}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002048static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2049#if SSL_OP_NO_TLSv1_3
2050 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2051 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002052#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002053}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002054#endif
2055static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2056static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002057
2058static struct {
2059 int option;
2060 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002061 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2062 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002063 const char *name;
2064} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002065 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2066 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2067 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2068 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2069 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2070 {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 +02002071};
2072
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002073static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2074{
2075 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2076 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2077 SSL_set_SSL_CTX(ssl, ctx);
2078}
2079
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002080#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002081
2082static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2083{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002084 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002085 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002086
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002087 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2088 return SSL_TLSEXT_ERR_OK;
2089 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002090}
2091
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002092#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002093static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2094{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002095 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002096#else
2097static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2098{
2099#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002100 struct connection *conn;
2101 struct bind_conf *s;
2102 const uint8_t *extension_data;
2103 size_t extension_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002104 int has_rsa = 0, has_ecdsa = 0, has_ecdsa_sig = 0;
2105
2106 char *wildp = NULL;
2107 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002108 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002109 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002110 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002111 int i;
2112
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002113 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002114 s = objt_listener(conn->target)->bind_conf;
2115
Olivier Houchard9679ac92017-10-27 14:58:08 +02002116 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002117 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002118#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002119 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2120 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002121#else
2122 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2123#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002124 /*
2125 * The server_name extension was given too much extensibility when it
2126 * was written, so parsing the normal case is a bit complex.
2127 */
2128 size_t len;
2129 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002130 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002131 /* Extract the length of the supplied list of names. */
2132 len = (*extension_data++) << 8;
2133 len |= *extension_data++;
2134 if (len + 2 != extension_len)
2135 goto abort;
2136 /*
2137 * The list in practice only has a single element, so we only consider
2138 * the first one.
2139 */
2140 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2141 goto abort;
2142 extension_len = len - 1;
2143 /* Now we can finally pull out the byte array with the actual hostname. */
2144 if (extension_len <= 2)
2145 goto abort;
2146 len = (*extension_data++) << 8;
2147 len |= *extension_data++;
2148 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2149 || memchr(extension_data, 0, len) != NULL)
2150 goto abort;
2151 servername = extension_data;
2152 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002153 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002154#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2155 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002156 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002157 }
2158#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002159 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002160 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002161 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002162 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002163 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002164 goto abort;
2165 }
2166
2167 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002168#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002169 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002170#else
2171 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2172#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002173 uint8_t sign;
2174 size_t len;
2175 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002176 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002177 len = (*extension_data++) << 8;
2178 len |= *extension_data++;
2179 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002180 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002181 if (len % 2 != 0)
2182 goto abort;
2183 for (; len > 0; len -= 2) {
2184 extension_data++; /* hash */
2185 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002186 switch (sign) {
2187 case TLSEXT_signature_rsa:
2188 has_rsa = 1;
2189 break;
2190 case TLSEXT_signature_ecdsa:
2191 has_ecdsa_sig = 1;
2192 break;
2193 default:
2194 continue;
2195 }
2196 if (has_ecdsa_sig && has_rsa)
2197 break;
2198 }
2199 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002200 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002201 has_rsa = 1;
2202 }
2203 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002204 const SSL_CIPHER *cipher;
2205 size_t len;
2206 const uint8_t *cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002207#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 len = ctx->cipher_suites_len;
2209 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002210#else
2211 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2212#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002213 if (len % 2 != 0)
2214 goto abort;
2215 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002216#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002217 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002218 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002219#else
2220 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2221#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002222 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002223 has_ecdsa = 1;
2224 break;
2225 }
2226 }
2227 }
2228
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002229 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002230 trash.area[i] = tolower(servername[i]);
2231 if (!wildp && (trash.area[i] == '.'))
2232 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002234 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002235
2236 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002237 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002238
2239 /* lookup a not neg filter */
2240 for (n = node; n; n = ebmb_next_dup(n)) {
2241 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002242 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002243 case TLSEXT_signature_ecdsa:
2244 if (has_ecdsa) {
2245 node_ecdsa = n;
2246 goto find_one;
2247 }
2248 break;
2249 case TLSEXT_signature_rsa:
2250 if (has_rsa && !node_rsa) {
2251 node_rsa = n;
2252 if (!has_ecdsa)
2253 goto find_one;
2254 }
2255 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002256 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002257 if (!node_anonymous)
2258 node_anonymous = n;
2259 break;
2260 }
2261 }
2262 }
2263 if (wildp) {
2264 /* lookup in wildcards names */
2265 node = ebst_lookup(&s->sni_w_ctx, wildp);
2266 for (n = node; n; n = ebmb_next_dup(n)) {
2267 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002268 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002269 case TLSEXT_signature_ecdsa:
2270 if (has_ecdsa) {
2271 node_ecdsa = n;
2272 goto find_one;
2273 }
2274 break;
2275 case TLSEXT_signature_rsa:
2276 if (has_rsa && !node_rsa) {
2277 node_rsa = n;
2278 if (!has_ecdsa)
2279 goto find_one;
2280 }
2281 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002282 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 if (!node_anonymous)
2284 node_anonymous = n;
2285 break;
2286 }
2287 }
2288 }
2289 }
2290 find_one:
2291 /* select by key_signature priority order */
2292 node = node_ecdsa ? node_ecdsa : (node_rsa ? node_rsa : node_anonymous);
2293
2294 if (node) {
2295 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002296 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002297 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002298 if (conf) {
2299 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2300 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2301 if (conf->early_data)
2302 allow_early = 1;
2303 }
2304 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002305 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002306#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002307 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002308 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002309 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002310 }
2311#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002312 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002313 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002314 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002315 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002316allow_early:
2317#ifdef OPENSSL_IS_BORINGSSL
2318 if (allow_early)
2319 SSL_set_early_data_enabled(ssl, 1);
2320#else
2321 if (!allow_early)
2322 SSL_set_max_early_data(ssl, 0);
2323#endif
2324 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002325 abort:
2326 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2327 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002328#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002329 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002330#else
2331 *al = SSL_AD_UNRECOGNIZED_NAME;
2332 return 0;
2333#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002334}
2335
2336#else /* OPENSSL_IS_BORINGSSL */
2337
Emeric Brunfc0421f2012-09-07 17:30:07 +02002338/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2339 * warning when no match is found, which implies the default (first) cert
2340 * will keep being used.
2341 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002342static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002343{
2344 const char *servername;
2345 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002346 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002347 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002348 int i;
2349 (void)al; /* shut gcc stupid warning */
2350
2351 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002352 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002353#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002354 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2355 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002356#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002357 if (s->strict_sni)
2358 return SSL_TLSEXT_ERR_ALERT_FATAL;
2359 ssl_sock_switchctx_set(ssl, s->default_ctx);
2360 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002361 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002362
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002363 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002364 if (!servername[i])
2365 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002366 trash.area[i] = tolower(servername[i]);
2367 if (!wildp && (trash.area[i] == '.'))
2368 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002369 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002370 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002371
2372 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002373 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002374
2375 /* lookup a not neg filter */
2376 for (n = node; n; n = ebmb_next_dup(n)) {
2377 if (!container_of(n, struct sni_ctx, name)->neg) {
2378 node = n;
2379 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002380 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002381 }
2382 if (!node && wildp) {
2383 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002384 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002385 }
2386 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002387#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002388 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2389 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002390 return SSL_TLSEXT_ERR_OK;
2391 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002392#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002393 if (s->strict_sni)
2394 return SSL_TLSEXT_ERR_ALERT_FATAL;
2395 ssl_sock_switchctx_set(ssl, s->default_ctx);
2396 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002397 }
2398
2399 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002400 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002401 return SSL_TLSEXT_ERR_OK;
2402}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002403#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002404#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2405
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002406#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002407
2408static DH * ssl_get_dh_1024(void)
2409{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002410 static unsigned char dh1024_p[]={
2411 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2412 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2413 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2414 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2415 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2416 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2417 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2418 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2419 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2420 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2421 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2422 };
2423 static unsigned char dh1024_g[]={
2424 0x02,
2425 };
2426
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002427 BIGNUM *p;
2428 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002429 DH *dh = DH_new();
2430 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002431 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2432 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002433
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002434 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002435 DH_free(dh);
2436 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002437 } else {
2438 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002439 }
2440 }
2441 return dh;
2442}
2443
2444static DH *ssl_get_dh_2048(void)
2445{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002446 static unsigned char dh2048_p[]={
2447 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2448 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2449 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2450 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2451 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2452 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2453 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2454 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2455 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2456 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2457 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2458 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2459 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2460 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2461 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2462 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2463 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2464 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2465 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2466 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2467 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2468 0xB7,0x1F,0x77,0xF3,
2469 };
2470 static unsigned char dh2048_g[]={
2471 0x02,
2472 };
2473
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002474 BIGNUM *p;
2475 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 DH *dh = DH_new();
2477 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002478 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2479 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002480
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002481 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002482 DH_free(dh);
2483 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002484 } else {
2485 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002486 }
2487 }
2488 return dh;
2489}
2490
2491static DH *ssl_get_dh_4096(void)
2492{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002493 static unsigned char dh4096_p[]={
2494 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2495 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2496 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2497 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2498 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2499 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2500 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2501 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2502 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2503 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2504 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2505 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2506 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2507 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2508 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2509 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2510 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2511 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2512 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2513 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2514 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2515 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2516 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2517 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2518 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2519 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2520 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2521 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2522 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2523 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2524 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2525 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2526 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2527 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2528 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2529 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2530 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2531 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2532 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2533 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2534 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2535 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2536 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002537 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002538 static unsigned char dh4096_g[]={
2539 0x02,
2540 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002541
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002542 BIGNUM *p;
2543 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002544 DH *dh = DH_new();
2545 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002546 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2547 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002548
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002549 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002550 DH_free(dh);
2551 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002552 } else {
2553 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002554 }
2555 }
2556 return dh;
2557}
2558
2559/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002560 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002561static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2562{
2563 DH *dh = NULL;
2564 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002565 int type;
2566
2567 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002568
2569 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2570 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2571 */
2572 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2573 keylen = EVP_PKEY_bits(pkey);
2574 }
2575
Willy Tarreauef934602016-12-22 23:12:01 +01002576 if (keylen > global_ssl.default_dh_param) {
2577 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578 }
2579
Remi Gacogned3a341a2015-05-29 16:26:17 +02002580 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002581 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002582 }
2583 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002584 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002585 }
2586 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002587 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002588 }
2589
2590 return dh;
2591}
2592
Remi Gacogne47783ef2015-05-29 15:53:22 +02002593static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002594{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002595 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002596 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002597
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002598 if (in == NULL)
2599 goto end;
2600
Remi Gacogne47783ef2015-05-29 15:53:22 +02002601 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002602 goto end;
2603
Remi Gacogne47783ef2015-05-29 15:53:22 +02002604 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2605
2606end:
2607 if (in)
2608 BIO_free(in);
2609
Emeric Brune1b4ed42018-08-16 15:14:12 +02002610 ERR_clear_error();
2611
Remi Gacogne47783ef2015-05-29 15:53:22 +02002612 return dh;
2613}
2614
2615int ssl_sock_load_global_dh_param_from_file(const char *filename)
2616{
2617 global_dh = ssl_sock_get_dh_from_file(filename);
2618
2619 if (global_dh) {
2620 return 0;
2621 }
2622
2623 return -1;
2624}
2625
2626/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
2627 if an error occured, and 0 if parameter not found. */
2628int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2629{
2630 int ret = -1;
2631 DH *dh = ssl_sock_get_dh_from_file(file);
2632
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002633 if (dh) {
2634 ret = 1;
2635 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002636
2637 if (ssl_dh_ptr_index >= 0) {
2638 /* store a pointer to the DH params to avoid complaining about
2639 ssl-default-dh-param not being set for this SSL_CTX */
2640 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2641 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002642 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002643 else if (global_dh) {
2644 SSL_CTX_set_tmp_dh(ctx, global_dh);
2645 ret = 0; /* DH params not found */
2646 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002647 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002648 /* Clear openssl global errors stack */
2649 ERR_clear_error();
2650
Willy Tarreauef934602016-12-22 23:12:01 +01002651 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002652 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002653 if (local_dh_1024 == NULL)
2654 local_dh_1024 = ssl_get_dh_1024();
2655
Remi Gacogne8de54152014-07-15 11:36:40 +02002656 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002657 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002658
Remi Gacogne8de54152014-07-15 11:36:40 +02002659 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002660 }
2661 else {
2662 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2663 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002664
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002665 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002666 }
Emeric Brun644cde02012-12-14 11:21:13 +01002667
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002668end:
2669 if (dh)
2670 DH_free(dh);
2671
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002672 return ret;
2673}
2674#endif
2675
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002676static 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 +02002677 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002678{
2679 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002680 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002681 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002682
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002683 if (*name == '!') {
2684 neg = 1;
2685 name++;
2686 }
2687 if (*name == '*') {
2688 wild = 1;
2689 name++;
2690 }
2691 /* !* filter is a nop */
2692 if (neg && wild)
2693 return order;
2694 if (*name) {
2695 int j, len;
2696 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002697 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002698 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002699 if (j >= trash.size)
2700 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002701 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002702
2703 /* Check for duplicates. */
2704 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002705 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002706 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002707 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002708 for (; node; node = ebmb_next_dup(node)) {
2709 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002710 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002711 return order;
2712 }
2713
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002714 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002715 if (!sc)
2716 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002717 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002718 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002719 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002720 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002721 sc->order = order++;
2722 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002723 if (kinfo.sig != TLSEXT_signature_anonymous)
2724 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002725 if (wild)
2726 ebst_insert(&s->sni_w_ctx, &sc->name);
2727 else
2728 ebst_insert(&s->sni_ctx, &sc->name);
2729 }
2730 return order;
2731}
2732
yanbzhu488a4d22015-12-01 15:16:07 -05002733
2734/* The following code is used for loading multiple crt files into
2735 * SSL_CTX's based on CN/SAN
2736 */
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01002737#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(LIBRESSL_VERSION_NUMBER)
yanbzhu488a4d22015-12-01 15:16:07 -05002738/* This is used to preload the certifcate, private key
2739 * and Cert Chain of a file passed in via the crt
2740 * argument
2741 *
2742 * This way, we do not have to read the file multiple times
2743 */
2744struct cert_key_and_chain {
2745 X509 *cert;
2746 EVP_PKEY *key;
2747 unsigned int num_chain_certs;
2748 /* This is an array of X509 pointers */
2749 X509 **chain_certs;
2750};
2751
yanbzhu08ce6ab2015-12-02 13:01:29 -05002752#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2753
2754struct key_combo_ctx {
2755 SSL_CTX *ctx;
2756 int order;
2757};
2758
2759/* Map used for processing multiple keypairs for a single purpose
2760 *
2761 * This maps CN/SNI name to certificate type
2762 */
2763struct sni_keytype {
2764 int keytypes; /* BITMASK for keytypes */
2765 struct ebmb_node name; /* node holding the servername value */
2766};
2767
2768
yanbzhu488a4d22015-12-01 15:16:07 -05002769/* Frees the contents of a cert_key_and_chain
2770 */
2771static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2772{
2773 int i;
2774
2775 if (!ckch)
2776 return;
2777
2778 /* Free the certificate and set pointer to NULL */
2779 if (ckch->cert)
2780 X509_free(ckch->cert);
2781 ckch->cert = NULL;
2782
2783 /* Free the key and set pointer to NULL */
2784 if (ckch->key)
2785 EVP_PKEY_free(ckch->key);
2786 ckch->key = NULL;
2787
2788 /* Free each certificate in the chain */
2789 for (i = 0; i < ckch->num_chain_certs; i++) {
2790 if (ckch->chain_certs[i])
2791 X509_free(ckch->chain_certs[i]);
2792 }
2793
2794 /* Free the chain obj itself and set to NULL */
2795 if (ckch->num_chain_certs > 0) {
2796 free(ckch->chain_certs);
2797 ckch->num_chain_certs = 0;
2798 ckch->chain_certs = NULL;
2799 }
2800
2801}
2802
2803/* checks if a key and cert exists in the ckch
2804 */
2805static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2806{
2807 return (ckch->cert != NULL && ckch->key != NULL);
2808}
2809
2810
2811/* Loads the contents of a crt file (path) into a cert_key_and_chain
2812 * This allows us to carry the contents of the file without having to
2813 * read the file multiple times.
2814 *
2815 * returns:
2816 * 0 on Success
2817 * 1 on SSL Failure
2818 * 2 on file not found
2819 */
2820static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2821{
2822
2823 BIO *in;
2824 X509 *ca = NULL;
2825 int ret = 1;
2826
2827 ssl_sock_free_cert_key_and_chain_contents(ckch);
2828
2829 in = BIO_new(BIO_s_file());
2830 if (in == NULL)
2831 goto end;
2832
2833 if (BIO_read_filename(in, path) <= 0)
2834 goto end;
2835
yanbzhu488a4d22015-12-01 15:16:07 -05002836 /* Read Private Key */
2837 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2838 if (ckch->key == NULL) {
2839 memprintf(err, "%sunable to load private key from file '%s'.\n",
2840 err && *err ? *err : "", path);
2841 goto end;
2842 }
2843
Willy Tarreaubb137a82016-04-06 19:02:38 +02002844 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002845 if (BIO_reset(in) == -1) {
2846 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2847 err && *err ? *err : "", path);
2848 goto end;
2849 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002850
2851 /* Read Certificate */
2852 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2853 if (ckch->cert == NULL) {
2854 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2855 err && *err ? *err : "", path);
2856 goto end;
2857 }
2858
yanbzhu488a4d22015-12-01 15:16:07 -05002859 /* Read Certificate Chain */
2860 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2861 /* Grow the chain certs */
2862 ckch->num_chain_certs++;
2863 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2864
2865 /* use - 1 here since we just incremented it above */
2866 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
2867 }
2868 ret = ERR_get_error();
2869 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2870 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2871 err && *err ? *err : "", path);
2872 ret = 1;
2873 goto end;
2874 }
2875
2876 ret = 0;
2877
2878end:
2879
2880 ERR_clear_error();
2881 if (in)
2882 BIO_free(in);
2883
2884 /* Something went wrong in one of the reads */
2885 if (ret != 0)
2886 ssl_sock_free_cert_key_and_chain_contents(ckch);
2887
2888 return ret;
2889}
2890
2891/* Loads the info in ckch into ctx
2892 * Currently, this does not process any information about ocsp, dhparams or
2893 * sctl
2894 * Returns
2895 * 0 on success
2896 * 1 on failure
2897 */
2898static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
2899{
2900 int i = 0;
2901
2902 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
2903 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
2904 err && *err ? *err : "", path);
2905 return 1;
2906 }
2907
2908 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
2909 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
2910 err && *err ? *err : "", path);
2911 return 1;
2912 }
2913
yanbzhu488a4d22015-12-01 15:16:07 -05002914 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
2915 for (i = 0; i < ckch->num_chain_certs; i++) {
2916 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05002917 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
2918 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05002919 return 1;
2920 }
2921 }
2922
2923 if (SSL_CTX_check_private_key(ctx) <= 0) {
2924 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2925 err && *err ? *err : "", path);
2926 return 1;
2927 }
2928
2929 return 0;
2930}
2931
yanbzhu08ce6ab2015-12-02 13:01:29 -05002932
2933static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
2934{
2935 struct sni_keytype *s_kt = NULL;
2936 struct ebmb_node *node;
2937 int i;
2938
2939 for (i = 0; i < trash.size; i++) {
2940 if (!str[i])
2941 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002942 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002943 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002944 trash.area[i] = 0;
2945 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002946 if (!node) {
2947 /* CN not found in tree */
2948 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
2949 /* Using memcpy here instead of strncpy.
2950 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
2951 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
2952 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002953 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05002954 s_kt->keytypes = 0;
2955 ebst_insert(sni_keytypes, &s_kt->name);
2956 } else {
2957 /* CN found in tree */
2958 s_kt = container_of(node, struct sni_keytype, name);
2959 }
2960
2961 /* Mark that this CN has the keytype of key_index via keytypes mask */
2962 s_kt->keytypes |= 1<<key_index;
2963
2964}
2965
2966
2967/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
2968 * If any are found, group these files into a set of SSL_CTX*
2969 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
2970 *
2971 * This will allow the user to explictly group multiple cert/keys for a single purpose
2972 *
2973 * Returns
2974 * 0 on success
2975 * 1 on failure
2976 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002977static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
2978 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05002979{
2980 char fp[MAXPATHLEN+1] = {0};
2981 int n = 0;
2982 int i = 0;
2983 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
2984 struct eb_root sni_keytypes_map = { {0} };
2985 struct ebmb_node *node;
2986 struct ebmb_node *next;
2987 /* Array of SSL_CTX pointers corresponding to each possible combo
2988 * of keytypes
2989 */
2990 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
2991 int rv = 0;
2992 X509_NAME *xname = NULL;
2993 char *str = NULL;
2994#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2995 STACK_OF(GENERAL_NAME) *names = NULL;
2996#endif
2997
2998 /* Load all possible certs and keys */
2999 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3000 struct stat buf;
3001
3002 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3003 if (stat(fp, &buf) == 0) {
3004 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3005 rv = 1;
3006 goto end;
3007 }
3008 }
3009 }
3010
3011 /* Process each ckch and update keytypes for each CN/SAN
3012 * for example, if CN/SAN www.a.com is associated with
3013 * certs with keytype 0 and 2, then at the end of the loop,
3014 * www.a.com will have:
3015 * keyindex = 0 | 1 | 4 = 5
3016 */
3017 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3018
3019 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3020 continue;
3021
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003022 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003023 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003024 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3025 } else {
3026 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3027 * so the line that contains logic is marked via comments
3028 */
3029 xname = X509_get_subject_name(certs_and_keys[n].cert);
3030 i = -1;
3031 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3032 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003033 ASN1_STRING *value;
3034 value = X509_NAME_ENTRY_get_data(entry);
3035 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003036 /* Important line is here */
3037 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003038
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003039 OPENSSL_free(str);
3040 str = NULL;
3041 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003042 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003043
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003044 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003045#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003046 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3047 if (names) {
3048 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3049 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003050
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003051 if (name->type == GEN_DNS) {
3052 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3053 /* Important line is here */
3054 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003055
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003056 OPENSSL_free(str);
3057 str = NULL;
3058 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003059 }
3060 }
3061 }
3062 }
3063#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3064 }
3065
3066 /* If no files found, return error */
3067 if (eb_is_empty(&sni_keytypes_map)) {
3068 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3069 err && *err ? *err : "", path);
3070 rv = 1;
3071 goto end;
3072 }
3073
3074 /* We now have a map of CN/SAN to keytypes that are loaded in
3075 * Iterate through the map to create the SSL_CTX's (if needed)
3076 * and add each CTX to the SNI tree
3077 *
3078 * Some math here:
3079 * There are 2^n - 1 possibile combinations, each unique
3080 * combination is denoted by the key in the map. Each key
3081 * has a value between 1 and 2^n - 1. Conveniently, the array
3082 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3083 * entry in the array to correspond to the unique combo (key)
3084 * associated with i. This unique key combo (i) will be associated
3085 * with combos[i-1]
3086 */
3087
3088 node = ebmb_first(&sni_keytypes_map);
3089 while (node) {
3090 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003091 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003092 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003093
3094 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3095 i = container_of(node, struct sni_keytype, name)->keytypes;
3096 cur_ctx = key_combos[i-1].ctx;
3097
3098 if (cur_ctx == NULL) {
3099 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003100 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003101 if (cur_ctx == NULL) {
3102 memprintf(err, "%sunable to allocate SSL context.\n",
3103 err && *err ? *err : "");
3104 rv = 1;
3105 goto end;
3106 }
3107
yanbzhube2774d2015-12-10 15:07:30 -05003108 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003109 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3110 if (i & (1<<n)) {
3111 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003112 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3113 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003114 SSL_CTX_free(cur_ctx);
3115 rv = 1;
3116 goto end;
3117 }
yanbzhube2774d2015-12-10 15:07:30 -05003118
3119#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3120 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003121 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003122 if (err)
3123 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 +00003124 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003125 SSL_CTX_free(cur_ctx);
3126 rv = 1;
3127 goto end;
3128 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003129#elif (defined OPENSSL_IS_BORINGSSL)
3130 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003131#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003132 }
3133 }
3134
3135 /* Load DH params into the ctx to support DHE keys */
3136#ifndef OPENSSL_NO_DH
3137 if (ssl_dh_ptr_index >= 0)
3138 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3139
3140 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3141 if (rv < 0) {
3142 if (err)
3143 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3144 *err ? *err : "", path);
3145 rv = 1;
3146 goto end;
3147 }
3148#endif
3149
3150 /* Update key_combos */
3151 key_combos[i-1].ctx = cur_ctx;
3152 }
3153
3154 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003155 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003156 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003157 node = ebmb_next(node);
3158 }
3159
3160
3161 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3162 if (!bind_conf->default_ctx) {
3163 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3164 if (key_combos[i].ctx) {
3165 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003166 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003167 break;
3168 }
3169 }
3170 }
3171
3172end:
3173
3174 if (names)
3175 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3176
3177 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3178 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3179
3180 node = ebmb_first(&sni_keytypes_map);
3181 while (node) {
3182 next = ebmb_next(node);
3183 ebmb_delete(node);
3184 node = next;
3185 }
3186
3187 return rv;
3188}
3189#else
3190/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003191static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3192 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003193{
3194 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3195 err && *err ? *err : "", path, strerror(errno));
3196 return 1;
3197}
3198
yanbzhu488a4d22015-12-01 15:16:07 -05003199#endif /* #if OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
3200
Emeric Brunfc0421f2012-09-07 17:30:07 +02003201/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3202 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3203 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003204static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3205 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003206{
3207 BIO *in;
3208 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003209 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003210 int ret = -1;
3211 int order = 0;
3212 X509_NAME *xname;
3213 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003214 pem_password_cb *passwd_cb;
3215 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003216 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003217 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003218
Emeric Brunfc0421f2012-09-07 17:30:07 +02003219#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3220 STACK_OF(GENERAL_NAME) *names;
3221#endif
3222
3223 in = BIO_new(BIO_s_file());
3224 if (in == NULL)
3225 goto end;
3226
3227 if (BIO_read_filename(in, file) <= 0)
3228 goto end;
3229
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003230
3231 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3232 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3233
3234 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003235 if (x == NULL)
3236 goto end;
3237
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003238 pkey = X509_get_pubkey(x);
3239 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003240 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003241 switch(EVP_PKEY_base_id(pkey)) {
3242 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003243 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003244 break;
3245 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003246 kinfo.sig = TLSEXT_signature_ecdsa;
3247 break;
3248 case EVP_PKEY_DSA:
3249 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003250 break;
3251 }
3252 EVP_PKEY_free(pkey);
3253 }
3254
Emeric Brun50bcecc2013-04-22 13:05:23 +02003255 if (fcount) {
3256 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003257 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003258 }
3259 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003260#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003261 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3262 if (names) {
3263 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3264 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3265 if (name->type == GEN_DNS) {
3266 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003267 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003268 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003269 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003270 }
3271 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003272 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003273 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003274#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003275 xname = X509_get_subject_name(x);
3276 i = -1;
3277 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3278 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003279 ASN1_STRING *value;
3280
3281 value = X509_NAME_ENTRY_get_data(entry);
3282 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003283 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003284 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003285 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003286 }
3287 }
3288
3289 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3290 if (!SSL_CTX_use_certificate(ctx, x))
3291 goto end;
3292
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003293#ifdef SSL_CTX_clear_extra_chain_certs
3294 SSL_CTX_clear_extra_chain_certs(ctx);
3295#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003296 if (ctx->extra_certs != NULL) {
3297 sk_X509_pop_free(ctx->extra_certs, X509_free);
3298 ctx->extra_certs = NULL;
3299 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003300#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003301
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003302 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003303 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3304 X509_free(ca);
3305 goto end;
3306 }
3307 }
3308
3309 err = ERR_get_error();
3310 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3311 /* we successfully reached the last cert in the file */
3312 ret = 1;
3313 }
3314 ERR_clear_error();
3315
3316end:
3317 if (x)
3318 X509_free(x);
3319
3320 if (in)
3321 BIO_free(in);
3322
3323 return ret;
3324}
3325
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003326static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3327 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003328{
3329 int ret;
3330 SSL_CTX *ctx;
3331
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003332 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003333 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003334 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3335 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003336 return 1;
3337 }
3338
3339 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003340 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3341 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003342 SSL_CTX_free(ctx);
3343 return 1;
3344 }
3345
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003346 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003347 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003348 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3349 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003350 if (ret < 0) /* serious error, must do that ourselves */
3351 SSL_CTX_free(ctx);
3352 return 1;
3353 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003354
3355 if (SSL_CTX_check_private_key(ctx) <= 0) {
3356 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3357 err && *err ? *err : "", path);
3358 return 1;
3359 }
3360
Emeric Brunfc0421f2012-09-07 17:30:07 +02003361 /* we must not free the SSL_CTX anymore below, since it's already in
3362 * the tree, so it will be discovered and cleaned in time.
3363 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003364#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003365 /* store a NULL pointer to indicate we have not yet loaded
3366 a custom DH param file */
3367 if (ssl_dh_ptr_index >= 0) {
3368 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3369 }
3370
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003371 ret = ssl_sock_load_dh_params(ctx, path);
3372 if (ret < 0) {
3373 if (err)
3374 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3375 *err ? *err : "", path);
3376 return 1;
3377 }
3378#endif
3379
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003380#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003381 ret = ssl_sock_load_ocsp(ctx, path);
3382 if (ret < 0) {
3383 if (err)
3384 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",
3385 *err ? *err : "", path);
3386 return 1;
3387 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003388#elif (defined OPENSSL_IS_BORINGSSL)
3389 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003390#endif
3391
Daniel Jakots54ffb912015-11-06 20:02:41 +01003392#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003393 if (sctl_ex_index >= 0) {
3394 ret = ssl_sock_load_sctl(ctx, path);
3395 if (ret < 0) {
3396 if (err)
3397 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3398 *err ? *err : "", path);
3399 return 1;
3400 }
3401 }
3402#endif
3403
Emeric Brunfc0421f2012-09-07 17:30:07 +02003404#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003405 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003406 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3407 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003408 return 1;
3409 }
3410#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003411 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003412 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003413 bind_conf->default_ssl_conf = ssl_conf;
3414 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003415
3416 return 0;
3417}
3418
Willy Tarreau03209342016-12-22 17:08:28 +01003419int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003420{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003421 struct dirent **de_list;
3422 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003423 DIR *dir;
3424 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003425 char *end;
3426 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003427 int cfgerr = 0;
yanbzhu63ea8462015-12-09 13:35:14 -05003428#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3429 int is_bundle;
3430 int j;
3431#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003432
yanbzhu08ce6ab2015-12-02 13:01:29 -05003433 if (stat(path, &buf) == 0) {
3434 dir = opendir(path);
3435 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003436 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003437
yanbzhu08ce6ab2015-12-02 13:01:29 -05003438 /* strip trailing slashes, including first one */
3439 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3440 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003441
yanbzhu08ce6ab2015-12-02 13:01:29 -05003442 n = scandir(path, &de_list, 0, alphasort);
3443 if (n < 0) {
3444 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3445 err && *err ? *err : "", path, strerror(errno));
3446 cfgerr++;
3447 }
3448 else {
3449 for (i = 0; i < n; i++) {
3450 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003451
yanbzhu08ce6ab2015-12-02 13:01:29 -05003452 end = strrchr(de->d_name, '.');
3453 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3454 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003455
yanbzhu08ce6ab2015-12-02 13:01:29 -05003456 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3457 if (stat(fp, &buf) != 0) {
3458 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3459 err && *err ? *err : "", fp, strerror(errno));
3460 cfgerr++;
3461 goto ignore_entry;
3462 }
3463 if (!S_ISREG(buf.st_mode))
3464 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003465
3466#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
3467 is_bundle = 0;
3468 /* Check if current entry in directory is part of a multi-cert bundle */
3469
3470 if (end) {
3471 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3472 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3473 is_bundle = 1;
3474 break;
3475 }
3476 }
3477
3478 if (is_bundle) {
3479 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3480 int dp_len;
3481
3482 dp_len = end - de->d_name;
3483 snprintf(dp, dp_len + 1, "%s", de->d_name);
3484
3485 /* increment i and free de until we get to a non-bundle cert
3486 * Note here that we look at de_list[i + 1] before freeing de
3487 * this is important since ignore_entry will free de
3488 */
3489 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3490 free(de);
3491 i++;
3492 de = de_list[i];
3493 }
3494
3495 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003496 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003497
3498 /* Successfully processed the bundle */
3499 goto ignore_entry;
3500 }
3501 }
3502
3503#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003504 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003505ignore_entry:
3506 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003507 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003508 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003509 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003510 closedir(dir);
3511 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003512 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003513
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003514 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003515
Emeric Brunfc0421f2012-09-07 17:30:07 +02003516 return cfgerr;
3517}
3518
Thierry Fournier383085f2013-01-24 14:15:43 +01003519/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3520 * done once. Zero is returned if the operation fails. No error is returned
3521 * if the random is said as not implemented, because we expect that openssl
3522 * will use another method once needed.
3523 */
3524static int ssl_initialize_random()
3525{
3526 unsigned char random;
3527 static int random_initialized = 0;
3528
3529 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3530 random_initialized = 1;
3531
3532 return random_initialized;
3533}
3534
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003535/* release ssl bind conf */
3536void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003537{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003538 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003539#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003540 free(conf->npn_str);
3541 conf->npn_str = NULL;
3542#endif
3543#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3544 free(conf->alpn_str);
3545 conf->alpn_str = NULL;
3546#endif
3547 free(conf->ca_file);
3548 conf->ca_file = NULL;
3549 free(conf->crl_file);
3550 conf->crl_file = NULL;
3551 free(conf->ciphers);
3552 conf->ciphers = NULL;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003553 free(conf->curves);
3554 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003555 free(conf->ecdhe);
3556 conf->ecdhe = NULL;
3557 }
3558}
3559
3560int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3561{
3562 char thisline[CRT_LINESIZE];
3563 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003564 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003565 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003566 int linenum = 0;
3567 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003568
Willy Tarreauad1731d2013-04-02 17:35:58 +02003569 if ((f = fopen(file, "r")) == NULL) {
3570 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003571 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003572 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003573
3574 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003575 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003576 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003577 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003578 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003579 char *crt_path;
3580 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003581
3582 linenum++;
3583 end = line + strlen(line);
3584 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3585 /* Check if we reached the limit and the last char is not \n.
3586 * Watch out for the last line without the terminating '\n'!
3587 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003588 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3589 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003590 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003591 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003592 }
3593
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003594 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003595 newarg = 1;
3596 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003597 if (*line == '#' || *line == '\n' || *line == '\r') {
3598 /* end of string, end of loop */
3599 *line = 0;
3600 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003601 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003602 newarg = 1;
3603 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003604 } else if (*line == '[') {
3605 if (ssl_b) {
3606 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3607 cfgerr = 1;
3608 break;
3609 }
3610 if (!arg) {
3611 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3612 cfgerr = 1;
3613 break;
3614 }
3615 ssl_b = arg;
3616 newarg = 1;
3617 *line = 0;
3618 } else if (*line == ']') {
3619 if (ssl_e) {
3620 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003621 cfgerr = 1;
3622 break;
3623 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003624 if (!ssl_b) {
3625 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3626 cfgerr = 1;
3627 break;
3628 }
3629 ssl_e = arg;
3630 newarg = 1;
3631 *line = 0;
3632 } else if (newarg) {
3633 if (arg == MAX_CRT_ARGS) {
3634 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3635 cfgerr = 1;
3636 break;
3637 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003638 newarg = 0;
3639 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003640 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003641 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003642 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003643 if (cfgerr)
3644 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003645 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003646
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003647 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003648 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003649 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003650
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003651 crt_path = args[0];
3652 if (*crt_path != '/' && global_ssl.crt_base) {
3653 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3654 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3655 crt_path, linenum, file);
3656 cfgerr = 1;
3657 break;
3658 }
3659 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3660 crt_path = path;
3661 }
3662
3663 ssl_conf = calloc(1, sizeof *ssl_conf);
3664 cur_arg = ssl_b ? ssl_b : 1;
3665 while (cur_arg < ssl_e) {
3666 newarg = 0;
3667 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3668 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3669 newarg = 1;
3670 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3671 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3672 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3673 args[cur_arg], linenum, file);
3674 cfgerr = 1;
3675 }
3676 cur_arg += 1 + ssl_bind_kws[i].skip;
3677 break;
3678 }
3679 }
3680 if (!cfgerr && !newarg) {
3681 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3682 args[cur_arg], linenum, file);
3683 cfgerr = 1;
3684 break;
3685 }
3686 }
3687 if (cfgerr) {
3688 ssl_sock_free_ssl_conf(ssl_conf);
3689 free(ssl_conf);
3690 ssl_conf = NULL;
3691 break;
3692 }
3693
3694 if (stat(crt_path, &buf) == 0) {
3695 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3696 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003697 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003698 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3699 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003700 }
3701
Willy Tarreauad1731d2013-04-02 17:35:58 +02003702 if (cfgerr) {
3703 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003704 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003705 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003706 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003707 fclose(f);
3708 return cfgerr;
3709}
3710
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003711/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003712static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003713ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003714{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003715 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003716 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003717 SSL_OP_ALL | /* all known workarounds for bugs */
3718 SSL_OP_NO_SSLv2 |
3719 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003720 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003721 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003722 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003723 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003724 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003725 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003726 SSL_MODE_ENABLE_PARTIAL_WRITE |
3727 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003728 SSL_MODE_RELEASE_BUFFERS |
3729 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003730 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003731 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003732 int flags = MC_SSL_O_ALL;
3733 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003734
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003735 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003736 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003737
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003738 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003739 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3740 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3741 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003742 else
3743 flags = conf_ssl_methods->flags;
3744
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003745 min = conf_ssl_methods->min;
3746 max = conf_ssl_methods->max;
3747 /* start with TLSv10 to remove SSLv3 per default */
3748 if (!min && (!max || max >= CONF_TLSV10))
3749 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003750 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003751 if (min)
3752 flags |= (methodVersions[min].flag - 1);
3753 if (max)
3754 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003755 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003756 min = max = CONF_TLSV_NONE;
3757 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003758 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003759 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003760 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003761 if (min) {
3762 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003763 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3764 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3765 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3766 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003767 hole = 0;
3768 }
3769 max = i;
3770 }
3771 else {
3772 min = max = i;
3773 }
3774 }
3775 else {
3776 if (min)
3777 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003778 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003779 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003780 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3781 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003782 cfgerr += 1;
3783 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003784 /* save real min/max in bind_conf */
3785 conf_ssl_methods->min = min;
3786 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003787
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02003788#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003789 /* Keep force-xxx implementation as it is in older haproxy. It's a
3790 precautionary measure to avoid any suprise with older openssl version. */
3791 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003792 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003793 else
3794 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3795 if (flags & methodVersions[i].flag)
3796 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003797#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003798 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003799 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3800 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003801#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003802
3803 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3804 options |= SSL_OP_NO_TICKET;
3805 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3806 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
3807 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003808
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02003809#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003810 if (global_ssl.async)
3811 mode |= SSL_MODE_ASYNC;
3812#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003813 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003814 if (global_ssl.life_time)
3815 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003816
3817#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3818#ifdef OPENSSL_IS_BORINGSSL
3819 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3820 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003821#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L)
3822 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3823 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003824#else
3825 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003826#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003827 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003828#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003829 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003830}
3831
William Lallemand4f45bb92017-10-30 20:08:51 +01003832
3833static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3834{
3835 if (first == block) {
3836 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3837 if (first->len > 0)
3838 sh_ssl_sess_tree_delete(sh_ssl_sess);
3839 }
3840}
3841
3842/* return first block from sh_ssl_sess */
3843static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3844{
3845 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3846
3847}
3848
3849/* store a session into the cache
3850 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3851 * data: asn1 encoded session
3852 * data_len: asn1 encoded session length
3853 * Returns 1 id session was stored (else 0)
3854 */
3855static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
3856{
3857 struct shared_block *first;
3858 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
3859
3860 first = shctx_row_reserve_hot(ssl_shctx, data_len + sizeof(struct sh_ssl_sess_hdr));
3861 if (!first) {
3862 /* Could not retrieve enough free blocks to store that session */
3863 return 0;
3864 }
3865
3866 /* STORE the key in the first elem */
3867 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3868 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
3869 first->len = sizeof(struct sh_ssl_sess_hdr);
3870
3871 /* it returns the already existing node
3872 or current node if none, never returns null */
3873 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
3874 if (oldsh_ssl_sess != sh_ssl_sess) {
3875 /* NOTE: Row couldn't be in use because we lock read & write function */
3876 /* release the reserved row */
3877 shctx_row_dec_hot(ssl_shctx, first);
3878 /* replace the previous session already in the tree */
3879 sh_ssl_sess = oldsh_ssl_sess;
3880 /* ignore the previous session data, only use the header */
3881 first = sh_ssl_sess_first_block(sh_ssl_sess);
3882 shctx_row_inc_hot(ssl_shctx, first);
3883 first->len = sizeof(struct sh_ssl_sess_hdr);
3884 }
3885
William Lallemand99b90af2018-01-03 19:15:51 +01003886 if (shctx_row_data_append(ssl_shctx, first, data, data_len) < 0) {
3887 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003888 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01003889 }
3890
3891 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01003892
3893 return 1;
3894}
William Lallemanded0b5ad2017-10-30 19:36:36 +01003895
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003896/* SSL callback used when a new session is created while connecting to a server */
3897static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
3898{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02003899 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01003900 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003901
Olivier Houcharde6060c52017-11-16 17:42:52 +01003902 s = objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003903
Olivier Houcharde6060c52017-11-16 17:42:52 +01003904 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
3905 int len;
3906 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003907
Olivier Houcharde6060c52017-11-16 17:42:52 +01003908 len = i2d_SSL_SESSION(sess, NULL);
3909 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
3910 ptr = s->ssl_ctx.reused_sess[tid].ptr;
3911 } else {
3912 free(s->ssl_ctx.reused_sess[tid].ptr);
3913 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
3914 s->ssl_ctx.reused_sess[tid].allocated_size = len;
3915 }
3916 if (s->ssl_ctx.reused_sess[tid].ptr) {
3917 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
3918 &ptr);
3919 }
3920 } else {
3921 free(s->ssl_ctx.reused_sess[tid].ptr);
3922 s->ssl_ctx.reused_sess[tid].ptr = NULL;
3923 }
3924
3925 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01003926}
3927
Olivier Houcharde6060c52017-11-16 17:42:52 +01003928
William Lallemanded0b5ad2017-10-30 19:36:36 +01003929/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01003930int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01003931{
3932 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
3933 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
3934 unsigned char *p;
3935 int data_len;
3936 unsigned int sid_length, sid_ctx_length;
3937 const unsigned char *sid_data;
3938 const unsigned char *sid_ctx_data;
3939
3940 /* Session id is already stored in to key and session id is known
3941 * so we dont store it to keep size.
3942 */
3943
3944 sid_data = SSL_SESSION_get_id(sess, &sid_length);
3945 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
3946 SSL_SESSION_set1_id(sess, sid_data, 0);
3947 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
3948
3949 /* check if buffer is large enough for the ASN1 encoded session */
3950 data_len = i2d_SSL_SESSION(sess, NULL);
3951 if (data_len > SHSESS_MAX_DATA_LEN)
3952 goto err;
3953
3954 p = encsess;
3955
3956 /* process ASN1 session encoding before the lock */
3957 i2d_SSL_SESSION(sess, &p);
3958
3959 memcpy(encid, sid_data, sid_length);
3960 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
3961 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
3962
William Lallemanda3c77cf2017-10-30 23:44:40 +01003963 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003964 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003965 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01003966 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003967err:
3968 /* reset original length values */
3969 SSL_SESSION_set1_id(sess, sid_data, sid_length);
3970 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
3971
3972 return 0; /* do not increment session reference count */
3973}
3974
3975/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01003976SSL_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 +01003977{
William Lallemand4f45bb92017-10-30 20:08:51 +01003978 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003979 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
3980 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01003981 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01003982 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01003983
3984 global.shctx_lookups++;
3985
3986 /* allow the session to be freed automatically by openssl */
3987 *do_copy = 0;
3988
3989 /* tree key is zeros padded sessionid */
3990 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
3991 memcpy(tmpkey, key, key_len);
3992 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
3993 key = tmpkey;
3994 }
3995
3996 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01003997 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01003998
3999 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004000 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4001 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004002 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004003 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004004 global.shctx_misses++;
4005 return NULL;
4006 }
4007
William Lallemand4f45bb92017-10-30 20:08:51 +01004008 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4009 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004010
William Lallemand4f45bb92017-10-30 20:08:51 +01004011 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 +01004012
William Lallemanda3c77cf2017-10-30 23:44:40 +01004013 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004014
4015 /* decode ASN1 session */
4016 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004017 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004018 /* Reset session id and session id contenxt */
4019 if (sess) {
4020 SSL_SESSION_set1_id(sess, key, key_len);
4021 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4022 }
4023
4024 return sess;
4025}
4026
William Lallemand4f45bb92017-10-30 20:08:51 +01004027
William Lallemanded0b5ad2017-10-30 19:36:36 +01004028/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004029void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004030{
William Lallemand4f45bb92017-10-30 20:08:51 +01004031 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004032 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4033 unsigned int sid_length;
4034 const unsigned char *sid_data;
4035 (void)ctx;
4036
4037 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4038 /* tree key is zeros padded sessionid */
4039 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4040 memcpy(tmpkey, sid_data, sid_length);
4041 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4042 sid_data = tmpkey;
4043 }
4044
William Lallemanda3c77cf2017-10-30 23:44:40 +01004045 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004046
4047 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004048 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4049 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004050 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004051 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004052 }
4053
4054 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004055 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004056}
4057
4058/* Set session cache mode to server and disable openssl internal cache.
4059 * Set shared cache callbacks on an ssl context.
4060 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004061void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004062{
4063 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4064
4065 if (!ssl_shctx) {
4066 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4067 return;
4068 }
4069
4070 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4071 SSL_SESS_CACHE_NO_INTERNAL |
4072 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4073
4074 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004075 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4076 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4077 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004078}
4079
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004080int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4081{
4082 struct proxy *curproxy = bind_conf->frontend;
4083 int cfgerr = 0;
4084 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004085 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004086 const char *conf_ciphers;
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004087 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004088
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004089 if (ssl_conf) {
4090 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4091 int i, min, max;
4092 int flags = MC_SSL_O_ALL;
4093
4094 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004095 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4096 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004097 if (min)
4098 flags |= (methodVersions[min].flag - 1);
4099 if (max)
4100 flags |= ~((methodVersions[max].flag << 1) - 1);
4101 min = max = CONF_TLSV_NONE;
4102 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4103 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4104 if (min)
4105 max = i;
4106 else
4107 min = max = i;
4108 }
4109 /* save real min/max */
4110 conf_ssl_methods->min = min;
4111 conf_ssl_methods->max = max;
4112 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004113 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4114 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004115 cfgerr += 1;
4116 }
4117 }
4118
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004119 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004120 case SSL_SOCK_VERIFY_NONE:
4121 verify = SSL_VERIFY_NONE;
4122 break;
4123 case SSL_SOCK_VERIFY_OPTIONAL:
4124 verify = SSL_VERIFY_PEER;
4125 break;
4126 case SSL_SOCK_VERIFY_REQUIRED:
4127 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4128 break;
4129 }
4130 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4131 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004132 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4133 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4134 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004135 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004136 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004137 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4138 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004139 cfgerr++;
4140 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004141 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4142 /* set CA names for client cert request, function returns void */
4143 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4144 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004145 }
Emeric Brun850efd52014-01-29 12:24:34 +01004146 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004147 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4148 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004149 cfgerr++;
4150 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004151#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004152 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004153 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4154
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004155 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004156 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4157 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004158 cfgerr++;
4159 }
Emeric Brun561e5742012-10-02 15:20:55 +02004160 else {
4161 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4162 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004163 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004164#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004165 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004166 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004167#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004168 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004169 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004170 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4171 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004172 cfgerr++;
4173 }
4174 }
4175#endif
4176
William Lallemand4f45bb92017-10-30 20:08:51 +01004177 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004178 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4179 if (conf_ciphers &&
4180 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004181 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4182 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004183 cfgerr++;
4184 }
4185
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004186#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004187 /* If tune.ssl.default-dh-param has not been set,
4188 neither has ssl-default-dh-file and no static DH
4189 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004190 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004191 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004192 (ssl_dh_ptr_index == -1 ||
4193 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004194 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4195 const SSL_CIPHER * cipher = NULL;
4196 char cipher_description[128];
4197 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4198 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4199 which is not ephemeral DH. */
4200 const char dhe_description[] = " Kx=DH ";
4201 const char dhe_export_description[] = " Kx=DH(";
4202 int idx = 0;
4203 int dhe_found = 0;
4204 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004205
Remi Gacogne23d5d372014-10-10 17:04:26 +02004206 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004207
Remi Gacogne23d5d372014-10-10 17:04:26 +02004208 if (ssl) {
4209 ciphers = SSL_get_ciphers(ssl);
4210
4211 if (ciphers) {
4212 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4213 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4214 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4215 if (strstr(cipher_description, dhe_description) != NULL ||
4216 strstr(cipher_description, dhe_export_description) != NULL) {
4217 dhe_found = 1;
4218 break;
4219 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004220 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004221 }
4222 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004223 SSL_free(ssl);
4224 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004225 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004226
Lukas Tribus90132722014-08-18 00:56:33 +02004227 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004228 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 +02004229 }
4230
Willy Tarreauef934602016-12-22 23:12:01 +01004231 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004232 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004233
Willy Tarreauef934602016-12-22 23:12:01 +01004234 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004235 if (local_dh_1024 == NULL) {
4236 local_dh_1024 = ssl_get_dh_1024();
4237 }
Willy Tarreauef934602016-12-22 23:12:01 +01004238 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004239 if (local_dh_2048 == NULL) {
4240 local_dh_2048 = ssl_get_dh_2048();
4241 }
Willy Tarreauef934602016-12-22 23:12:01 +01004242 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004243 if (local_dh_4096 == NULL) {
4244 local_dh_4096 = ssl_get_dh_4096();
4245 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004246 }
4247 }
4248 }
4249#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004250
Emeric Brunfc0421f2012-09-07 17:30:07 +02004251 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004252#if OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004253 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004254#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004255
Bernard Spil13c53f82018-02-15 13:34:58 +01004256#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004257 ssl_conf_cur = NULL;
4258 if (ssl_conf && ssl_conf->npn_str)
4259 ssl_conf_cur = ssl_conf;
4260 else if (bind_conf->ssl_conf.npn_str)
4261 ssl_conf_cur = &bind_conf->ssl_conf;
4262 if (ssl_conf_cur)
4263 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004264#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004265#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004266 ssl_conf_cur = NULL;
4267 if (ssl_conf && ssl_conf->alpn_str)
4268 ssl_conf_cur = ssl_conf;
4269 else if (bind_conf->ssl_conf.alpn_str)
4270 ssl_conf_cur = &bind_conf->ssl_conf;
4271 if (ssl_conf_cur)
4272 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004273#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004274#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
4275 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4276 if (conf_curves) {
4277 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004278 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4279 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004280 cfgerr++;
4281 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004282#if defined(SSL_CTX_set_ecdh_auto)
4283 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4284#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004285 }
4286#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004287#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004288 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004289 int i;
4290 EC_KEY *ecdh;
Olivier Houchardc2aae742017-09-22 18:26:28 +02004291#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004292 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004293 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4294 NULL);
4295
4296 if (ecdhe == NULL) {
4297 SSL_CTX_set_dh_auto(ctx, 1);
4298 return cfgerr;
4299 }
4300#else
4301 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4302 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4303 ECDHE_DEFAULT_CURVE);
4304#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004305
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004306 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004307 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004308 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4309 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004310 cfgerr++;
4311 }
4312 else {
4313 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4314 EC_KEY_free(ecdh);
4315 }
4316 }
4317#endif
4318
Emeric Brunfc0421f2012-09-07 17:30:07 +02004319 return cfgerr;
4320}
4321
Evan Broderbe554312013-06-27 00:05:25 -07004322static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4323{
4324 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4325 size_t prefixlen, suffixlen;
4326
4327 /* Trivial case */
4328 if (strcmp(pattern, hostname) == 0)
4329 return 1;
4330
Evan Broderbe554312013-06-27 00:05:25 -07004331 /* The rest of this logic is based on RFC 6125, section 6.4.3
4332 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4333
Emeric Bruna848dae2013-10-08 11:27:28 +02004334 pattern_wildcard = NULL;
4335 pattern_left_label_end = pattern;
4336 while (*pattern_left_label_end != '.') {
4337 switch (*pattern_left_label_end) {
4338 case 0:
4339 /* End of label not found */
4340 return 0;
4341 case '*':
4342 /* If there is more than one wildcards */
4343 if (pattern_wildcard)
4344 return 0;
4345 pattern_wildcard = pattern_left_label_end;
4346 break;
4347 }
4348 pattern_left_label_end++;
4349 }
4350
4351 /* If it's not trivial and there is no wildcard, it can't
4352 * match */
4353 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004354 return 0;
4355
4356 /* Make sure all labels match except the leftmost */
4357 hostname_left_label_end = strchr(hostname, '.');
4358 if (!hostname_left_label_end
4359 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4360 return 0;
4361
4362 /* Make sure the leftmost label of the hostname is long enough
4363 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004364 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004365 return 0;
4366
4367 /* Finally compare the string on either side of the
4368 * wildcard */
4369 prefixlen = pattern_wildcard - pattern;
4370 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004371 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4372 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004373 return 0;
4374
4375 return 1;
4376}
4377
4378static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4379{
4380 SSL *ssl;
4381 struct connection *conn;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004382 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004383 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004384
4385 int depth;
4386 X509 *cert;
4387 STACK_OF(GENERAL_NAME) *alt_names;
4388 int i;
4389 X509_NAME *cert_subject;
4390 char *str;
4391
4392 if (ok == 0)
4393 return ok;
4394
4395 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004396 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Evan Broderbe554312013-06-27 00:05:25 -07004397
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004398 /* We're checking if the provided hostnames match the desired one. The
4399 * desired hostname comes from the SNI we presented if any, or if not
4400 * provided then it may have been explicitly stated using a "verifyhost"
4401 * directive. If neither is set, we don't care about the name so the
4402 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004403 */
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004404 servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004405 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004406 if (!servername) {
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004407 servername = objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004408 if (!servername)
4409 return ok;
4410 }
Evan Broderbe554312013-06-27 00:05:25 -07004411
4412 /* We only need to verify the CN on the actual server cert,
4413 * not the indirect CAs */
4414 depth = X509_STORE_CTX_get_error_depth(ctx);
4415 if (depth != 0)
4416 return ok;
4417
4418 /* At this point, the cert is *not* OK unless we can find a
4419 * hostname match */
4420 ok = 0;
4421
4422 cert = X509_STORE_CTX_get_current_cert(ctx);
4423 /* It seems like this might happen if verify peer isn't set */
4424 if (!cert)
4425 return ok;
4426
4427 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4428 if (alt_names) {
4429 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4430 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4431 if (name->type == GEN_DNS) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004432#if OPENSSL_VERSION_NUMBER < 0x00907000L
4433 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4434#else
Evan Broderbe554312013-06-27 00:05:25 -07004435 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004436#endif
Evan Broderbe554312013-06-27 00:05:25 -07004437 ok = ssl_sock_srv_hostcheck(str, servername);
4438 OPENSSL_free(str);
4439 }
4440 }
4441 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004442 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004443 }
4444
4445 cert_subject = X509_get_subject_name(cert);
4446 i = -1;
4447 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4448 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004449 ASN1_STRING *value;
4450 value = X509_NAME_ENTRY_get_data(entry);
4451 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004452 ok = ssl_sock_srv_hostcheck(str, servername);
4453 OPENSSL_free(str);
4454 }
4455 }
4456
Willy Tarreau71d058c2017-07-26 20:09:56 +02004457 /* report the mismatch and indicate if SNI was used or not */
4458 if (!ok && !conn->err_code)
4459 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004460 return ok;
4461}
4462
Emeric Brun94324a42012-10-11 14:00:19 +02004463/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004464int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004465{
Willy Tarreau03209342016-12-22 17:08:28 +01004466 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004467 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004468 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004469 SSL_OP_ALL | /* all known workarounds for bugs */
4470 SSL_OP_NO_SSLv2 |
4471 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004472 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004473 SSL_MODE_ENABLE_PARTIAL_WRITE |
4474 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004475 SSL_MODE_RELEASE_BUFFERS |
4476 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004477 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004478 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004479 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004480 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004481 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004482
Thierry Fournier383085f2013-01-24 14:15:43 +01004483 /* Make sure openssl opens /dev/urandom before the chroot */
4484 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004485 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004486 cfgerr++;
4487 }
4488
Willy Tarreaufce03112015-01-15 21:32:40 +01004489 /* Automatic memory computations need to know we use SSL there */
4490 global.ssl_used_backend = 1;
4491
4492 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004493 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004494 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4496 curproxy->id, srv->id,
4497 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004498 cfgerr++;
4499 return cfgerr;
4500 }
4501 }
Emeric Brun94324a42012-10-11 14:00:19 +02004502 if (srv->use_ssl)
4503 srv->xprt = &ssl_sock;
4504 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004505 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004506
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004507 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004508 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004509 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4510 proxy_type_str(curproxy), curproxy->id,
4511 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004512 cfgerr++;
4513 return cfgerr;
4514 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004515
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004516 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004517 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4518 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4519 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004520 else
4521 flags = conf_ssl_methods->flags;
4522
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004523 /* Real min and max should be determinate with configuration and openssl's capabilities */
4524 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004525 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004526 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004527 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004528
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004529 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004530 min = max = CONF_TLSV_NONE;
4531 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004532 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004533 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004534 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004535 if (min) {
4536 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004537 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4538 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4539 proxy_type_str(curproxy), curproxy->id, srv->id,
4540 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004541 hole = 0;
4542 }
4543 max = i;
4544 }
4545 else {
4546 min = max = i;
4547 }
4548 }
4549 else {
4550 if (min)
4551 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004552 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004553 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004554 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4555 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004556 cfgerr += 1;
4557 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004558
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02004559#if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004560 /* Keep force-xxx implementation as it is in older haproxy. It's a
4561 precautionary measure to avoid any suprise with older openssl version. */
4562 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004563 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004564 else
4565 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4566 if (flags & methodVersions[i].flag)
4567 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004568#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004569 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004570 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4571 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004572#endif
4573
4574 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4575 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004576 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004577
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02004578#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004579 if (global_ssl.async)
4580 mode |= SSL_MODE_ASYNC;
4581#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004582 SSL_CTX_set_mode(ctx, mode);
4583 srv->ssl_ctx.ctx = ctx;
4584
Emeric Bruna7aa3092012-10-26 12:58:00 +02004585 if (srv->ssl_ctx.client_crt) {
4586 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 +01004587 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4588 proxy_type_str(curproxy), curproxy->id,
4589 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004590 cfgerr++;
4591 }
4592 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 +01004593 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4594 proxy_type_str(curproxy), curproxy->id,
4595 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004596 cfgerr++;
4597 }
4598 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004599 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4600 proxy_type_str(curproxy), curproxy->id,
4601 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004602 cfgerr++;
4603 }
4604 }
Emeric Brun94324a42012-10-11 14:00:19 +02004605
Emeric Brun850efd52014-01-29 12:24:34 +01004606 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4607 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004608 switch (srv->ssl_ctx.verify) {
4609 case SSL_SOCK_VERIFY_NONE:
4610 verify = SSL_VERIFY_NONE;
4611 break;
4612 case SSL_SOCK_VERIFY_REQUIRED:
4613 verify = SSL_VERIFY_PEER;
4614 break;
4615 }
Evan Broderbe554312013-06-27 00:05:25 -07004616 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004617 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004618 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004619 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004620 if (srv->ssl_ctx.ca_file) {
4621 /* load CAfile to verify */
4622 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004623 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4624 curproxy->id, srv->id,
4625 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004626 cfgerr++;
4627 }
4628 }
Emeric Brun850efd52014-01-29 12:24:34 +01004629 else {
4630 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004631 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",
4632 curproxy->id, srv->id,
4633 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004634 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004635 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4636 curproxy->id, srv->id,
4637 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004638 cfgerr++;
4639 }
Emeric Brunef42d922012-10-11 16:11:36 +02004640#ifdef X509_V_FLAG_CRL_CHECK
4641 if (srv->ssl_ctx.crl_file) {
4642 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4643
4644 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004645 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4646 curproxy->id, srv->id,
4647 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004648 cfgerr++;
4649 }
4650 else {
4651 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4652 }
4653 }
4654#endif
4655 }
4656
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004657 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4658 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4659 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004660 if (srv->ssl_ctx.ciphers &&
4661 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004662 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4663 curproxy->id, srv->id,
4664 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004665 cfgerr++;
4666 }
4667
4668 return cfgerr;
4669}
4670
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004671/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004672 * be NULL, in which case nothing is done. Returns the number of errors
4673 * encountered.
4674 */
Willy Tarreau03209342016-12-22 17:08:28 +01004675int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004676{
4677 struct ebmb_node *node;
4678 struct sni_ctx *sni;
4679 int err = 0;
4680
Willy Tarreaufce03112015-01-15 21:32:40 +01004681 /* Automatic memory computations need to know we use SSL there */
4682 global.ssl_used_frontend = 1;
4683
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004684 /* Make sure openssl opens /dev/urandom before the chroot */
4685 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004686 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004687 err++;
4688 }
4689 /* Create initial_ctx used to start the ssl connection before do switchctx */
4690 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004691 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004692 /* It should not be necessary to call this function, but it's
4693 necessary first to check and move all initialisation related
4694 to initial_ctx in ssl_sock_initial_ctx. */
4695 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4696 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004697 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004698 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004699
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004700 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004701 while (node) {
4702 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004703 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4704 /* only initialize the CTX on its first occurrence and
4705 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004706 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004707 node = ebmb_next(node);
4708 }
4709
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004710 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004711 while (node) {
4712 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004713 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4714 /* only initialize the CTX on its first occurrence and
4715 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004716 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004717 node = ebmb_next(node);
4718 }
4719 return err;
4720}
4721
Willy Tarreau55d37912016-12-21 23:38:39 +01004722/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4723 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4724 * alerts are directly emitted since the rest of the stack does it below.
4725 */
4726int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4727{
4728 struct proxy *px = bind_conf->frontend;
4729 int alloc_ctx;
4730 int err;
4731
4732 if (!bind_conf->is_ssl) {
4733 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004734 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4735 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004736 }
4737 return 0;
4738 }
4739 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004740 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004741 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4742 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004743 }
4744 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004745 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4746 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004747 return -1;
4748 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004749 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004750 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004751 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
4752 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE,
4753 sizeof(*sh_ssl_sess_tree),
4754 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
4755 if (alloc_ctx < 0) {
4756 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4757 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");
4758 else
4759 ha_alert("Unable to allocate SSL session cache.\n");
4760 return -1;
4761 }
4762 /* free block callback */
4763 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4764 /* init the root tree within the extra space */
4765 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4766 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004767 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004768 err = 0;
4769 /* initialize all certificate contexts */
4770 err += ssl_sock_prepare_all_ctx(bind_conf);
4771
4772 /* initialize CA variables if the certificates generation is enabled */
4773 err += ssl_sock_load_ca(bind_conf);
4774
4775 return -err;
4776}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004777
4778/* release ssl context allocated for servers. */
4779void ssl_sock_free_srv_ctx(struct server *srv)
4780{
4781 if (srv->ssl_ctx.ctx)
4782 SSL_CTX_free(srv->ssl_ctx.ctx);
4783}
4784
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004785/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004786 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4787 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004788void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004789{
4790 struct ebmb_node *node, *back;
4791 struct sni_ctx *sni;
4792
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004793 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004794 while (node) {
4795 sni = ebmb_entry(node, struct sni_ctx, name);
4796 back = ebmb_next(node);
4797 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004798 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004799 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004800 ssl_sock_free_ssl_conf(sni->conf);
4801 free(sni->conf);
4802 sni->conf = NULL;
4803 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004804 free(sni);
4805 node = back;
4806 }
4807
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004808 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004809 while (node) {
4810 sni = ebmb_entry(node, struct sni_ctx, name);
4811 back = ebmb_next(node);
4812 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004813 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004814 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004815 ssl_sock_free_ssl_conf(sni->conf);
4816 free(sni->conf);
4817 sni->conf = NULL;
4818 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004819 free(sni);
4820 node = back;
4821 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004822 SSL_CTX_free(bind_conf->initial_ctx);
4823 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004824 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004825 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02004826}
4827
Willy Tarreau795cdab2016-12-22 17:30:54 +01004828/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
4829void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
4830{
4831 ssl_sock_free_ca(bind_conf);
4832 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004833 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01004834 free(bind_conf->ca_sign_file);
4835 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02004836 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01004837 free(bind_conf->keys_ref->filename);
4838 free(bind_conf->keys_ref->tlskeys);
4839 LIST_DEL(&bind_conf->keys_ref->list);
4840 free(bind_conf->keys_ref);
4841 }
4842 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004843 bind_conf->ca_sign_pass = NULL;
4844 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01004845}
4846
Christopher Faulet31af49d2015-06-09 17:29:50 +02004847/* Load CA cert file and private key used to generate certificates */
4848int
Willy Tarreau03209342016-12-22 17:08:28 +01004849ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004850{
Willy Tarreau03209342016-12-22 17:08:28 +01004851 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004852 FILE *fp;
4853 X509 *cacert = NULL;
4854 EVP_PKEY *capkey = NULL;
4855 int err = 0;
4856
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02004857 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02004858 return err;
4859
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01004860#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02004861 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01004862 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01004863 HA_RWLOCK_INIT(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004864 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02004865 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004866 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02004867#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02004868
Christopher Faulet31af49d2015-06-09 17:29:50 +02004869 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004870 ha_alert("Proxy '%s': cannot enable certificate generation, "
4871 "no CA certificate File configured at [%s:%d].\n",
4872 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004873 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004874 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004875
4876 /* read in the CA certificate */
4877 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004878 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4879 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004880 goto load_error;
4881 }
4882 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004883 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
4884 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004885 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004886 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004887 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004888 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004889 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
4890 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004891 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004892 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02004893
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004894 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004895 bind_conf->ca_sign_cert = cacert;
4896 bind_conf->ca_sign_pkey = capkey;
4897 return err;
4898
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004899 read_error:
4900 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02004901 if (capkey) EVP_PKEY_free(capkey);
4902 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02004903 load_error:
4904 bind_conf->generate_certs = 0;
4905 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004906 return err;
4907}
4908
4909/* Release CA cert and private key used to generate certificated */
4910void
4911ssl_sock_free_ca(struct bind_conf *bind_conf)
4912{
Christopher Faulet31af49d2015-06-09 17:29:50 +02004913 if (bind_conf->ca_sign_pkey)
4914 EVP_PKEY_free(bind_conf->ca_sign_pkey);
4915 if (bind_conf->ca_sign_cert)
4916 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01004917 bind_conf->ca_sign_pkey = NULL;
4918 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02004919}
4920
Emeric Brun46591952012-05-18 15:47:34 +02004921/*
4922 * This function is called if SSL * context is not yet allocated. The function
4923 * is designed to be called before any other data-layer operation and sets the
4924 * handshake flag on the connection. It is safe to call it multiple times.
4925 * It returns 0 on success and -1 in error case.
4926 */
4927static int ssl_sock_init(struct connection *conn)
4928{
4929 /* already initialized */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02004930 if (conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02004931 return 0;
4932
Willy Tarreau3c728722014-01-23 13:50:42 +01004933 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02004934 return 0;
4935
Willy Tarreau20879a02012-12-03 16:32:10 +01004936 if (global.maxsslconn && sslconns >= global.maxsslconn) {
4937 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02004938 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004939 }
Willy Tarreau403edff2012-09-06 11:58:37 +02004940
Emeric Brun46591952012-05-18 15:47:34 +02004941 /* If it is in client mode initiate SSL session
4942 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004943 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004944 int may_retry = 1;
4945
4946 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02004947 /* Alloc a new SSL session ctx */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004948 conn->xprt_ctx = SSL_new(objt_server(conn->target)->ssl_ctx.ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01004949 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004950 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004951 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004952 goto retry_connect;
4953 }
Willy Tarreau20879a02012-12-03 16:32:10 +01004954 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02004955 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01004956 }
Emeric Brun46591952012-05-18 15:47:34 +02004957
Emeric Brun46591952012-05-18 15:47:34 +02004958 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02004959 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01004960 SSL_free(conn->xprt_ctx);
4961 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004962 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004963 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004964 goto retry_connect;
4965 }
Emeric Brun55476152014-11-12 17:35:37 +01004966 conn->err_code = CO_ER_SSL_NO_MEM;
4967 return -1;
4968 }
Emeric Brun46591952012-05-18 15:47:34 +02004969
Evan Broderbe554312013-06-27 00:05:25 -07004970 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004971 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01004972 SSL_free(conn->xprt_ctx);
4973 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004974 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01004975 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01004976 goto retry_connect;
4977 }
Emeric Brun55476152014-11-12 17:35:37 +01004978 conn->err_code = CO_ER_SSL_NO_MEM;
4979 return -1;
4980 }
4981
4982 SSL_set_connect_state(conn->xprt_ctx);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004983 if (objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
4984 const unsigned char *ptr = objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
4985 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
4986 if(sess && !SSL_set_session(conn->xprt_ctx, sess)) {
4987 SSL_SESSION_free(sess);
4988 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
4989 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
4990 } else if (sess) {
4991 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01004992 }
4993 }
Evan Broderbe554312013-06-27 00:05:25 -07004994
Emeric Brun46591952012-05-18 15:47:34 +02004995 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02004996 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02004997
4998 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01004999 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005000 return 0;
5001 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005002 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005003 int may_retry = 1;
5004
5005 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005006 /* Alloc a new SSL session ctx */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005007 conn->xprt_ctx = SSL_new(objt_listener(conn->target)->bind_conf->initial_ctx);
Willy Tarreau20879a02012-12-03 16:32:10 +01005008 if (!conn->xprt_ctx) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005009 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005010 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005011 goto retry_accept;
5012 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005013 conn->err_code = CO_ER_SSL_NO_MEM;
Emeric Brun46591952012-05-18 15:47:34 +02005014 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005015 }
Emeric Brun46591952012-05-18 15:47:34 +02005016
Emeric Brun46591952012-05-18 15:47:34 +02005017 /* set fd on SSL session context */
Willy Tarreau585744b2017-08-24 14:31:19 +02005018 if (!SSL_set_fd(conn->xprt_ctx, conn->handle.fd)) {
Emeric Brun55476152014-11-12 17:35:37 +01005019 SSL_free(conn->xprt_ctx);
5020 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005021 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005022 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005023 goto retry_accept;
5024 }
Emeric Brun55476152014-11-12 17:35:37 +01005025 conn->err_code = CO_ER_SSL_NO_MEM;
5026 return -1;
5027 }
Emeric Brun46591952012-05-18 15:47:34 +02005028
Emeric Brune1f38db2012-09-03 20:36:47 +02005029 /* set connection pointer */
Thierry FOURNIER28962c92018-06-17 21:37:05 +02005030 if (!SSL_set_ex_data(conn->xprt_ctx, ssl_app_data_index, conn)) {
Emeric Brun55476152014-11-12 17:35:37 +01005031 SSL_free(conn->xprt_ctx);
5032 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005033 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005034 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005035 goto retry_accept;
5036 }
Emeric Brun55476152014-11-12 17:35:37 +01005037 conn->err_code = CO_ER_SSL_NO_MEM;
5038 return -1;
5039 }
5040
5041 SSL_set_accept_state(conn->xprt_ctx);
Emeric Brune1f38db2012-09-03 20:36:47 +02005042
Emeric Brun46591952012-05-18 15:47:34 +02005043 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005044 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005045#if OPENSSL_VERSION_NUMBER >= 0x10101000L || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005046 conn->flags |= CO_FL_EARLY_SSL_HS;
5047#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005048
5049 sslconns++;
Willy Tarreau71b734c2014-01-28 15:19:44 +01005050 totalsslconns++;
Emeric Brun46591952012-05-18 15:47:34 +02005051 return 0;
5052 }
5053 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005054 conn->err_code = CO_ER_SSL_NO_TARGET;
Emeric Brun46591952012-05-18 15:47:34 +02005055 return -1;
5056}
5057
5058
5059/* This is the callback which is used when an SSL handshake is pending. It
5060 * updates the FD status if it wants some polling before being called again.
5061 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5062 * otherwise it returns non-zero and removes itself from the connection's
5063 * flags (the bit is provided in <flag> by the caller).
5064 */
5065int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5066{
5067 int ret;
5068
Willy Tarreau3c728722014-01-23 13:50:42 +01005069 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005070 return 0;
5071
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005072 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005073 goto out_error;
5074
Olivier Houchardc2aae742017-09-22 18:26:28 +02005075#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5076 /*
5077 * Check if we have early data. If we do, we have to read them
5078 * before SSL_do_handshake() is called, And there's no way to
5079 * detect early data, except to try to read them
5080 */
5081 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5082 size_t read_data;
5083
5084 ret = SSL_read_early_data(conn->xprt_ctx, &conn->tmp_early_data,
5085 1, &read_data);
5086 if (ret == SSL_READ_EARLY_DATA_ERROR)
5087 goto check_error;
5088 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5089 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5090 return 1;
5091 } else
5092 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5093 }
5094#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005095 /* If we use SSL_do_handshake to process a reneg initiated by
5096 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5097 * Usually SSL_write and SSL_read are used and process implicitly
5098 * the reneg handshake.
5099 * Here we use SSL_peek as a workaround for reneg.
5100 */
5101 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(conn->xprt_ctx)) {
5102 char c;
5103
5104 ret = SSL_peek(conn->xprt_ctx, &c, 1);
5105 if (ret <= 0) {
5106 /* handshake may have not been completed, let's find why */
5107 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005108
Emeric Brun674b7432012-11-08 19:21:55 +01005109 if (ret == SSL_ERROR_WANT_WRITE) {
5110 /* SSL handshake needs to write, L4 connection may not be ready */
5111 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005112 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005113 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005114 return 0;
5115 }
5116 else if (ret == SSL_ERROR_WANT_READ) {
5117 /* handshake may have been completed but we have
5118 * no more data to read.
5119 */
5120 if (!SSL_renegotiate_pending(conn->xprt_ctx)) {
5121 ret = 1;
5122 goto reneg_ok;
5123 }
5124 /* SSL handshake needs to read, L4 connection is ready */
5125 if (conn->flags & CO_FL_WAIT_L4_CONN)
5126 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5127 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005128 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005129 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005130 return 0;
5131 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005132#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005133 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005134 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005135 return 0;
5136 }
5137#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005138 else if (ret == SSL_ERROR_SYSCALL) {
5139 /* if errno is null, then connection was successfully established */
5140 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5141 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005142 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005143#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005144 conn->err_code = CO_ER_SSL_HANDSHAKE;
5145#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005146 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005147#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005148 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5149 empty_handshake = state == TLS_ST_BEFORE;
5150#else
5151 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
5152#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005153 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005154 if (!errno) {
5155 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5156 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5157 else
5158 conn->err_code = CO_ER_SSL_EMPTY;
5159 }
5160 else {
5161 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5162 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5163 else
5164 conn->err_code = CO_ER_SSL_ABORT;
5165 }
5166 }
5167 else {
5168 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5169 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005170 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005171 conn->err_code = CO_ER_SSL_HANDSHAKE;
5172 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005173#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005174 }
Emeric Brun674b7432012-11-08 19:21:55 +01005175 goto out_error;
5176 }
5177 else {
5178 /* Fail on all other handshake errors */
5179 /* Note: OpenSSL may leave unread bytes in the socket's
5180 * buffer, causing an RST to be emitted upon close() on
5181 * TCP sockets. We first try to drain possibly pending
5182 * data to avoid this as much as possible.
5183 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005184 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005185 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005186 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5187 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005188 goto out_error;
5189 }
5190 }
5191 /* read some data: consider handshake completed */
5192 goto reneg_ok;
5193 }
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005194 ret = SSL_do_handshake(conn->xprt_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005195check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005196 if (ret != 1) {
5197 /* handshake did not complete, let's find why */
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005198 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005199
5200 if (ret == SSL_ERROR_WANT_WRITE) {
5201 /* SSL handshake needs to write, L4 connection may not be ready */
5202 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005203 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005204 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005205 return 0;
5206 }
5207 else if (ret == SSL_ERROR_WANT_READ) {
5208 /* SSL handshake needs to read, L4 connection is ready */
5209 if (conn->flags & CO_FL_WAIT_L4_CONN)
5210 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5211 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005212 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005213 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005214 return 0;
5215 }
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005216#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005217 else if (ret == SSL_ERROR_WANT_ASYNC) {
Emeric Brun3854e012017-05-17 20:42:48 +02005218 ssl_async_process_fds(conn, conn->xprt_ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005219 return 0;
5220 }
5221#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005222 else if (ret == SSL_ERROR_SYSCALL) {
5223 /* if errno is null, then connection was successfully established */
5224 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5225 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005226 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005227#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005228 conn->err_code = CO_ER_SSL_HANDSHAKE;
5229#else
5230 int empty_handshake;
Luca Pizzamiglio578b1692016-12-12 10:56:56 +01005231#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(LIBRESSL_VERSION_NUMBER)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005232 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)conn->xprt_ctx);
5233 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005234#else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005235 empty_handshake = !((SSL *)conn->xprt_ctx)->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005236#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005237 if (empty_handshake) {
5238 if (!errno) {
5239 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5240 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5241 else
5242 conn->err_code = CO_ER_SSL_EMPTY;
5243 }
5244 else {
5245 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5246 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5247 else
5248 conn->err_code = CO_ER_SSL_ABORT;
5249 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005250 }
5251 else {
5252 if (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
5253 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5254 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005255 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005256 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005257#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005258 }
Willy Tarreau89230192012-09-28 20:22:13 +02005259 goto out_error;
5260 }
Emeric Brun46591952012-05-18 15:47:34 +02005261 else {
5262 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005263 /* Note: OpenSSL may leave unread bytes in the socket's
5264 * buffer, causing an RST to be emitted upon close() on
5265 * TCP sockets. We first try to drain possibly pending
5266 * data to avoid this as much as possible.
5267 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005268 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005269 if (!conn->err_code)
Willy Tarreauf51c6982014-04-25 20:02:39 +02005270 conn->err_code = (conn->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
5271 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005272 goto out_error;
5273 }
5274 }
Olivier Houchard522eea72017-11-03 16:27:47 +01005275#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5276 else {
5277 /*
5278 * If the server refused the early data, we have to send a
5279 * 425 to the client, as we no longer have the data to sent
5280 * them again.
5281 */
5282 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
5283 if (SSL_get_early_data_status(conn->xprt_ctx) == SSL_EARLY_DATA_REJECTED) {
5284 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5285 goto out_error;
5286 }
5287 }
5288 }
5289#endif
5290
Emeric Brun46591952012-05-18 15:47:34 +02005291
Emeric Brun674b7432012-11-08 19:21:55 +01005292reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005293
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005294#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005295 /* ASYNC engine API doesn't support moving read/write
5296 * buffers. So we disable ASYNC mode right after
5297 * the handshake to avoid buffer oveflows.
5298 */
5299 if (global_ssl.async)
5300 SSL_clear_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5301#endif
Emeric Brun46591952012-05-18 15:47:34 +02005302 /* Handshake succeeded */
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005303 if (!SSL_session_reused(conn->xprt_ctx)) {
5304 if (objt_server(conn->target)) {
5305 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5306 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5307 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005308 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005309 else {
5310 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5311 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5312 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5313 }
Emeric Brun46591952012-05-18 15:47:34 +02005314 }
5315
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005316#ifdef OPENSSL_IS_BORINGSSL
5317 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(conn->xprt_ctx))
5318 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5319#endif
Emeric Brun46591952012-05-18 15:47:34 +02005320 /* The connection is now established at both layers, it's time to leave */
5321 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5322 return 1;
5323
5324 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005325 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005326 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005327 ERR_clear_error();
5328
Emeric Brun9fa89732012-10-04 17:09:56 +02005329 /* free resumed session if exists */
Olivier Houcharde6060c52017-11-16 17:42:52 +01005330 if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5331 free(objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5332 objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005333 }
5334
Emeric Brun46591952012-05-18 15:47:34 +02005335 /* Fail on all other handshake errors */
5336 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005337 if (!conn->err_code)
5338 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005339 return 0;
5340}
5341
5342/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005343 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005344 * buffer wraps, in which case a second call may be performed. The connection's
5345 * flags are updated with whatever special event is detected (error, read0,
5346 * empty). The caller is responsible for taking care of those events and
5347 * avoiding the call if inappropriate. The function does not call the
5348 * connection's polling update function, so the caller is responsible for this.
5349 */
Willy Tarreau7f3225f2018-06-19 06:15:17 +02005350static size_t ssl_sock_to_buf(struct connection *conn, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005351{
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005352 ssize_t ret;
5353 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005354
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005355 conn_refresh_polling_flags(conn);
5356
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005357 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005358 goto out_error;
5359
5360 if (conn->flags & CO_FL_HANDSHAKE)
5361 /* a handshake was requested */
5362 return 0;
5363
Willy Tarreau0c7ed5d2018-07-10 09:53:31 +02005364 b_realign_if_empty(buf);
Emeric Brun46591952012-05-18 15:47:34 +02005365
5366 /* read the largest possible block. For this, we perform only one call
5367 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5368 * in which case we accept to do it once again. A new attempt is made on
5369 * EINTR too.
5370 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005371 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005372 int need_out = 0;
5373
Willy Tarreau591d4452018-06-15 17:21:00 +02005374 try = b_contig_space(buf);
5375 if (!try)
5376 break;
5377
Willy Tarreauabf08d92014-01-14 11:31:27 +01005378 if (try > count)
5379 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005380
Olivier Houchardc2aae742017-09-22 18:26:28 +02005381 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
5382 conn->tmp_early_data != -1) {
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005383 *b_tail(buf) = conn->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005384 done++;
5385 try--;
5386 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005387 b_add(buf, 1);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005388 conn->tmp_early_data = -1;
5389 continue;
5390 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005391
Olivier Houchardc2aae742017-09-22 18:26:28 +02005392#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5393 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5394 size_t read_length;
5395
5396 ret = SSL_read_early_data(conn->xprt_ctx,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005397 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005398 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5399 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005400 conn->flags |= CO_FL_EARLY_DATA;
5401 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5402 ret == SSL_READ_EARLY_DATA_FINISH) {
5403 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5404 /*
5405 * We're done reading the early data,
5406 * let's make the handshake
5407 */
5408 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5409 conn->flags |= CO_FL_SSL_WAIT_HS;
5410 need_out = 1;
5411 if (read_length == 0)
5412 break;
5413 }
5414 ret = read_length;
5415 }
5416 } else
5417#endif
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005418 ret = SSL_read(conn->xprt_ctx, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005419#ifdef OPENSSL_IS_BORINGSSL
5420 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5421 if (SSL_in_early_data(conn->xprt_ctx)) {
5422 if (ret > 0)
5423 conn->flags |= CO_FL_EARLY_DATA;
5424 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005425 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005426 }
5427 }
5428#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005429 if (conn->flags & CO_FL_ERROR) {
5430 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005431 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005432 }
Emeric Brun46591952012-05-18 15:47:34 +02005433 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005434 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005435 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005436 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005437 }
Emeric Brun46591952012-05-18 15:47:34 +02005438 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005439 ret = SSL_get_error(conn->xprt_ctx, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005440 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005441 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005442 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005443 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005444#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005445 /* Async mode can be re-enabled, because we're leaving data state.*/
5446 if (global_ssl.async)
5447 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5448#endif
Emeric Brun46591952012-05-18 15:47:34 +02005449 break;
5450 }
5451 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005452 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5453 /* handshake is running, and it may need to re-enable read */
5454 conn->flags |= CO_FL_SSL_WAIT_HS;
5455 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005456#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005457 /* Async mode can be re-enabled, because we're leaving data state.*/
5458 if (global_ssl.async)
5459 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5460#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005461 break;
5462 }
Emeric Brun46591952012-05-18 15:47:34 +02005463 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005464 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005465 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005466 } else if (ret == SSL_ERROR_ZERO_RETURN)
5467 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005468 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5469 * stack before shutting down the connection for
5470 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005471 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5472 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005473 /* otherwise it's a real error */
5474 goto out_error;
5475 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005476 if (need_out)
5477 break;
Emeric Brun46591952012-05-18 15:47:34 +02005478 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005479 leave:
5480 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005481 return done;
5482
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005483 clear_ssl_error:
5484 /* Clear openssl global errors stack */
5485 ssl_sock_dump_errors(conn);
5486 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005487 read0:
5488 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005489 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005490
Emeric Brun46591952012-05-18 15:47:34 +02005491 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005492 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005493 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005494 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005495 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005496 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005497}
5498
5499
Willy Tarreau787db9a2018-06-14 18:31:46 +02005500/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5501 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5502 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005503 * Only one call to send() is performed, unless the buffer wraps, in which case
5504 * a second call may be performed. The connection's flags are updated with
5505 * whatever special event is detected (error, empty). The caller is responsible
5506 * for taking care of those events and avoiding the call if inappropriate. The
5507 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005508 * is responsible for this. The buffer's output is not adjusted, it's up to the
5509 * caller to take care of this. It's up to the caller to update the buffer's
5510 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005511 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005512static 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 +02005513{
Willy Tarreau787db9a2018-06-14 18:31:46 +02005514 ssize_t ret;
5515 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005516
5517 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005518 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005519
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005520 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005521 goto out_error;
5522
5523 if (conn->flags & CO_FL_HANDSHAKE)
5524 /* a handshake was requested */
5525 return 0;
5526
5527 /* send the largest possible block. For this we perform only one call
5528 * to send() unless the buffer wraps and we exactly fill the first hunk,
5529 * in which case we accept to do it once again.
5530 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005531 while (count) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005532#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5533 size_t written_data;
5534#endif
5535
Willy Tarreau787db9a2018-06-14 18:31:46 +02005536 try = b_contig_data(buf, done);
5537 if (try > count)
5538 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005539
Willy Tarreau7bed9452014-02-02 02:00:24 +01005540 if (!(flags & CO_SFL_STREAMER) &&
Willy Tarreau518cedd2014-02-17 15:43:01 +01005541 !(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005542 global_ssl.max_record && try > global_ssl.max_record) {
5543 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005544 }
5545 else {
5546 /* we need to keep the information about the fact that
5547 * we're not limiting the upcoming send(), because if it
5548 * fails, we'll have to retry with at least as many data.
5549 */
5550 conn->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
5551 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005552
Olivier Houchardc2aae742017-09-22 18:26:28 +02005553#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
5554 if (!SSL_is_init_finished(conn->xprt_ctx)) {
5555 unsigned int max_early;
5556
Olivier Houchard522eea72017-11-03 16:27:47 +01005557 if (objt_listener(conn->target))
5558 max_early = SSL_get_max_early_data(conn->xprt_ctx);
5559 else {
5560 if (SSL_get0_session(conn->xprt_ctx))
5561 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(conn->xprt_ctx));
5562 else
5563 max_early = 0;
5564 }
5565
Olivier Houchard90084a12017-11-23 18:21:29 +01005566 if (try + conn->sent_early_data > max_early) {
5567 try -= (try + conn->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005568 if (try <= 0) {
Olivier Houchard90084a12017-11-23 18:21:29 +01005569 if (!(conn->flags & CO_FL_EARLY_SSL_HS))
5570 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005571 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005572 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005573 }
Willy Tarreau787db9a2018-06-14 18:31:46 +02005574 ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005575 if (ret == 1) {
5576 ret = written_data;
Olivier Houchard90084a12017-11-23 18:21:29 +01005577 conn->sent_early_data += ret;
Olivier Houchard522eea72017-11-03 16:27:47 +01005578 if (objt_server(conn->target)) {
5579 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5580 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
5581 }
5582
Olivier Houchardc2aae742017-09-22 18:26:28 +02005583 }
5584
5585 } else
5586#endif
Willy Tarreau787db9a2018-06-14 18:31:46 +02005587 ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005588
Emeric Brune1f38db2012-09-03 20:36:47 +02005589 if (conn->flags & CO_FL_ERROR) {
5590 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005591 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005592 }
Emeric Brun46591952012-05-18 15:47:34 +02005593 if (ret > 0) {
Willy Tarreau518cedd2014-02-17 15:43:01 +01005594 conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005595 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005596 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005597 }
5598 else {
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005599 ret = SSL_get_error(conn->xprt_ctx, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005600
Emeric Brun46591952012-05-18 15:47:34 +02005601 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005602 if (SSL_renegotiate_pending(conn->xprt_ctx)) {
5603 /* handshake is running, and it may need to re-enable write */
5604 conn->flags |= CO_FL_SSL_WAIT_HS;
5605 __conn_sock_want_send(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005606#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005607 /* Async mode can be re-enabled, because we're leaving data state.*/
5608 if (global_ssl.async)
5609 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5610#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005611 break;
5612 }
Emeric Brun46591952012-05-18 15:47:34 +02005613 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005614 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005615 break;
5616 }
5617 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005618 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005619 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005620 __conn_sock_want_recv(conn);
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005621#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005622 /* Async mode can be re-enabled, because we're leaving data state.*/
5623 if (global_ssl.async)
5624 SSL_set_mode(conn->xprt_ctx, SSL_MODE_ASYNC);
5625#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005626 break;
5627 }
Emeric Brun46591952012-05-18 15:47:34 +02005628 goto out_error;
5629 }
5630 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005631 leave:
5632 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005633 return done;
5634
5635 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005636 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005637 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005638 ERR_clear_error();
5639
Emeric Brun46591952012-05-18 15:47:34 +02005640 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005641 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005642}
5643
Emeric Brun46591952012-05-18 15:47:34 +02005644static void ssl_sock_close(struct connection *conn) {
5645
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005646 if (conn->xprt_ctx) {
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02005647#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005648 if (global_ssl.async) {
5649 OSSL_ASYNC_FD all_fd[32], afd;
5650 size_t num_all_fds = 0;
5651 int i;
5652
5653 SSL_get_all_async_fds(conn->xprt_ctx, NULL, &num_all_fds);
5654 if (num_all_fds > 32) {
5655 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5656 return;
5657 }
5658
5659 SSL_get_all_async_fds(conn->xprt_ctx, all_fd, &num_all_fds);
5660
5661 /* If an async job is pending, we must try to
5662 to catch the end using polling before calling
5663 SSL_free */
5664 if (num_all_fds && SSL_waiting_for_async(conn->xprt_ctx)) {
5665 for (i=0 ; i < num_all_fds ; i++) {
5666 /* switch on an handler designed to
5667 * handle the SSL_free
5668 */
5669 afd = all_fd[i];
5670 fdtab[afd].iocb = ssl_async_fd_free;
5671 fdtab[afd].owner = conn->xprt_ctx;
5672 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005673 /* To ensure that the fd cache won't be used
5674 * and we'll catch a real RD event.
5675 */
5676 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005677 }
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005678 conn->xprt_ctx = NULL;
Christopher Faulet8d8aa0d2017-05-30 15:36:50 +02005679 HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005680 return;
5681 }
Emeric Brun3854e012017-05-17 20:42:48 +02005682 /* Else we can remove the fds from the fdtab
5683 * and call SSL_free.
5684 * note: we do a fd_remove and not a delete
5685 * because the fd is owned by the engine.
5686 * the engine is responsible to close
5687 */
5688 for (i=0 ; i < num_all_fds ; i++)
5689 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005690 }
5691#endif
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005692 SSL_free(conn->xprt_ctx);
5693 conn->xprt_ctx = NULL;
Willy Tarreau403edff2012-09-06 11:58:37 +02005694 sslconns--;
Emeric Brun46591952012-05-18 15:47:34 +02005695 }
Emeric Brun46591952012-05-18 15:47:34 +02005696}
5697
5698/* This function tries to perform a clean shutdown on an SSL connection, and in
5699 * any case, flags the connection as reusable if no handshake was in progress.
5700 */
5701static void ssl_sock_shutw(struct connection *conn, int clean)
5702{
5703 if (conn->flags & CO_FL_HANDSHAKE)
5704 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005705 if (!clean)
5706 /* don't sent notify on SSL_shutdown */
Willy Tarreaue3cc3a32017-02-13 11:12:29 +01005707 SSL_set_quiet_shutdown(conn->xprt_ctx, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005708 /* no handshake was in progress, try a clean ssl shutdown */
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005709 if (SSL_shutdown(conn->xprt_ctx) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005710 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005711 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005712 ERR_clear_error();
5713 }
Emeric Brun46591952012-05-18 15:47:34 +02005714}
5715
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005716/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005717int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005718{
5719 struct pkey_info *pkinfo;
5720 int bits = 0;
5721 int sig = TLSEXT_signature_anonymous;
5722 int len = -1;
5723
5724 if (!ssl_sock_is_ssl(conn))
5725 return 0;
5726
Emmanuel Hocdet3448c492018-06-18 12:44:19 +02005727 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(conn->xprt_ctx), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005728 if (pkinfo) {
5729 sig = pkinfo->sig;
5730 bits = pkinfo->bits;
5731 } else {
5732 /* multicert and generated cert have no pkey info */
5733 X509 *crt;
5734 EVP_PKEY *pkey;
5735 crt = SSL_get_certificate(conn->xprt_ctx);
5736 if (!crt)
5737 return 0;
5738 pkey = X509_get_pubkey(crt);
5739 if (pkey) {
5740 bits = EVP_PKEY_bits(pkey);
5741 switch(EVP_PKEY_base_id(pkey)) {
5742 case EVP_PKEY_RSA:
5743 sig = TLSEXT_signature_rsa;
5744 break;
5745 case EVP_PKEY_EC:
5746 sig = TLSEXT_signature_ecdsa;
5747 break;
5748 case EVP_PKEY_DSA:
5749 sig = TLSEXT_signature_dsa;
5750 break;
5751 }
5752 EVP_PKEY_free(pkey);
5753 }
5754 }
5755
5756 switch(sig) {
5757 case TLSEXT_signature_rsa:
5758 len = chunk_printf(out, "RSA%d", bits);
5759 break;
5760 case TLSEXT_signature_ecdsa:
5761 len = chunk_printf(out, "EC%d", bits);
5762 break;
5763 case TLSEXT_signature_dsa:
5764 len = chunk_printf(out, "DSA%d", bits);
5765 break;
5766 default:
5767 return 0;
5768 }
5769 if (len < 0)
5770 return 0;
5771 return 1;
5772}
5773
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01005774/* used for ppv2 cert signature (can be used for logging) */
5775const char *ssl_sock_get_cert_sig(struct connection *conn)
5776{
5777 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
5778 X509 *crt;
5779
5780 if (!ssl_sock_is_ssl(conn))
5781 return NULL;
5782 crt = SSL_get_certificate(conn->xprt_ctx);
5783 if (!crt)
5784 return NULL;
5785 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
5786 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
5787}
5788
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01005789/* used for ppv2 authority */
5790const char *ssl_sock_get_sni(struct connection *conn)
5791{
5792#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
5793 if (!ssl_sock_is_ssl(conn))
5794 return NULL;
5795 return SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
5796#else
5797 return 0;
5798#endif
5799}
5800
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005801/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005802const char *ssl_sock_get_cipher_name(struct connection *conn)
5803{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005804 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005805 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005806
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005807 return SSL_get_cipher_name(conn->xprt_ctx);
5808}
5809
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005810/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005811const char *ssl_sock_get_proto_version(struct connection *conn)
5812{
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005813 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005814 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02005815
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02005816 return SSL_get_version(conn->xprt_ctx);
5817}
5818
Willy Tarreau8d598402012-10-22 17:58:39 +02005819/* Extract a serial from a cert, and copy it to a chunk.
5820 * Returns 1 if serial is found and copied, 0 if no serial found and
5821 * -1 if output is not large enough.
5822 */
5823static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005824ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02005825{
5826 ASN1_INTEGER *serial;
5827
5828 serial = X509_get_serialNumber(crt);
5829 if (!serial)
5830 return 0;
5831
5832 if (out->size < serial->length)
5833 return -1;
5834
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005835 memcpy(out->area, serial->data, serial->length);
5836 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02005837 return 1;
5838}
5839
Emeric Brun43e79582014-10-29 19:03:26 +01005840/* Extract a cert to der, and copy it to a chunk.
5841 * Returns 1 if cert is found and copied, 0 on der convertion failure and
5842 * -1 if output is not large enough.
5843 */
5844static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005845ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01005846{
5847 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005848 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01005849
5850 len =i2d_X509(crt, NULL);
5851 if (len <= 0)
5852 return 1;
5853
5854 if (out->size < len)
5855 return -1;
5856
5857 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005858 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01005859 return 1;
5860}
5861
Emeric Brunce5ad802012-10-22 14:11:22 +02005862
Willy Tarreau83061a82018-07-13 11:56:34 +02005863/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02005864 * Returns 1 if serial is found and copied, 0 if no valid time found
5865 * and -1 if output is not large enough.
5866 */
5867static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005868ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02005869{
5870 if (tm->type == V_ASN1_GENERALIZEDTIME) {
5871 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
5872
5873 if (gentm->length < 12)
5874 return 0;
5875 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
5876 return 0;
5877 if (out->size < gentm->length-2)
5878 return -1;
5879
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005880 memcpy(out->area, gentm->data+2, gentm->length-2);
5881 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02005882 return 1;
5883 }
5884 else if (tm->type == V_ASN1_UTCTIME) {
5885 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
5886
5887 if (utctm->length < 10)
5888 return 0;
5889 if (utctm->data[0] >= 0x35)
5890 return 0;
5891 if (out->size < utctm->length)
5892 return -1;
5893
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005894 memcpy(out->area, utctm->data, utctm->length);
5895 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02005896 return 1;
5897 }
5898
5899 return 0;
5900}
5901
Emeric Brun87855892012-10-17 17:39:35 +02005902/* Extract an entry from a X509_NAME and copy its value to an output chunk.
5903 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
5904 */
5905static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005906ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
5907 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005908{
5909 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005910 ASN1_OBJECT *obj;
5911 ASN1_STRING *data;
5912 const unsigned char *data_ptr;
5913 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005914 int i, j, n;
5915 int cur = 0;
5916 const char *s;
5917 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005918 int name_count;
5919
5920 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005921
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005922 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005923 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02005924 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005925 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02005926 else
5927 j = i;
5928
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005929 ne = X509_NAME_get_entry(a, j);
5930 obj = X509_NAME_ENTRY_get_object(ne);
5931 data = X509_NAME_ENTRY_get_data(ne);
5932 data_ptr = ASN1_STRING_get0_data(data);
5933 data_len = ASN1_STRING_length(data);
5934 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005935 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005936 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005937 s = tmp;
5938 }
5939
5940 if (chunk_strcasecmp(entry, s) != 0)
5941 continue;
5942
5943 if (pos < 0)
5944 cur--;
5945 else
5946 cur++;
5947
5948 if (cur != pos)
5949 continue;
5950
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005951 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02005952 return -1;
5953
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005954 memcpy(out->area, data_ptr, data_len);
5955 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005956 return 1;
5957 }
5958
5959 return 0;
5960
5961}
5962
5963/* Extract and format full DN from a X509_NAME and copy result into a chunk
5964 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
5965 */
5966static int
Willy Tarreau83061a82018-07-13 11:56:34 +02005967ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02005968{
5969 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005970 ASN1_OBJECT *obj;
5971 ASN1_STRING *data;
5972 const unsigned char *data_ptr;
5973 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02005974 int i, n, ln;
5975 int l = 0;
5976 const char *s;
5977 char *p;
5978 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005979 int name_count;
5980
5981
5982 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02005983
Willy Tarreau843b7cb2018-07-13 10:54:26 +02005984 out->data = 0;
5985 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005986 for (i = 0; i < name_count; i++) {
5987 ne = X509_NAME_get_entry(a, i);
5988 obj = X509_NAME_ENTRY_get_object(ne);
5989 data = X509_NAME_ENTRY_get_data(ne);
5990 data_ptr = ASN1_STRING_get0_data(data);
5991 data_len = ASN1_STRING_length(data);
5992 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02005993 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005994 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02005995 s = tmp;
5996 }
5997 ln = strlen(s);
5998
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005999 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006000 if (l > out->size)
6001 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006002 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006003
6004 *(p++)='/';
6005 memcpy(p, s, ln);
6006 p += ln;
6007 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006008 memcpy(p, data_ptr, data_len);
6009 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006010 }
6011
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006012 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006013 return 0;
6014
6015 return 1;
6016}
6017
Willy Tarreau119a4082016-12-22 21:58:38 +01006018/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6019 * to disable SNI.
6020 */
Willy Tarreau63076412015-07-10 11:33:32 +02006021void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6022{
6023#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau119a4082016-12-22 21:58:38 +01006024 char *prev_name;
6025
Willy Tarreau63076412015-07-10 11:33:32 +02006026 if (!ssl_sock_is_ssl(conn))
6027 return;
6028
Willy Tarreau119a4082016-12-22 21:58:38 +01006029 /* if the SNI changes, we must destroy the reusable context so that a
6030 * new connection will present a new SNI. As an optimization we could
6031 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6032 * server.
6033 */
6034 prev_name = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6035 if ((!prev_name && hostname) ||
6036 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
6037 SSL_set_session(conn->xprt_ctx, NULL);
6038
Willy Tarreau63076412015-07-10 11:33:32 +02006039 SSL_set_tlsext_host_name(conn->xprt_ctx, hostname);
6040#endif
6041}
6042
Emeric Brun0abf8362014-06-24 18:26:41 +02006043/* Extract peer certificate's common name into the chunk dest
6044 * Returns
6045 * the len of the extracted common name
6046 * or 0 if no CN found in DN
6047 * or -1 on error case (i.e. no peer certificate)
6048 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006049int ssl_sock_get_remote_common_name(struct connection *conn,
6050 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006051{
6052 X509 *crt = NULL;
6053 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006054 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006055 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006056 .area = (char *)&find_cn,
6057 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006058 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006059 int result = -1;
David Safb76832014-05-08 23:42:08 -04006060
6061 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006062 goto out;
David Safb76832014-05-08 23:42:08 -04006063
6064 /* SSL_get_peer_certificate, it increase X509 * ref count */
6065 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6066 if (!crt)
6067 goto out;
6068
6069 name = X509_get_subject_name(crt);
6070 if (!name)
6071 goto out;
David Safb76832014-05-08 23:42:08 -04006072
Emeric Brun0abf8362014-06-24 18:26:41 +02006073 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6074out:
David Safb76832014-05-08 23:42:08 -04006075 if (crt)
6076 X509_free(crt);
6077
6078 return result;
6079}
6080
Dave McCowan328fb582014-07-30 10:39:13 -04006081/* returns 1 if client passed a certificate for this session, 0 if not */
6082int ssl_sock_get_cert_used_sess(struct connection *conn)
6083{
6084 X509 *crt = NULL;
6085
6086 if (!ssl_sock_is_ssl(conn))
6087 return 0;
6088
6089 /* SSL_get_peer_certificate, it increase X509 * ref count */
6090 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6091 if (!crt)
6092 return 0;
6093
6094 X509_free(crt);
6095 return 1;
6096}
6097
6098/* returns 1 if client passed a certificate for this connection, 0 if not */
6099int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006100{
6101 if (!ssl_sock_is_ssl(conn))
6102 return 0;
6103
6104 return SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
6105}
6106
6107/* returns result from SSL verify */
6108unsigned int ssl_sock_get_verify_result(struct connection *conn)
6109{
6110 if (!ssl_sock_is_ssl(conn))
6111 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6112
6113 return (unsigned int)SSL_get_verify_result(conn->xprt_ctx);
6114}
6115
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006116/* Returns the application layer protocol name in <str> and <len> when known.
6117 * Zero is returned if the protocol name was not found, otherwise non-zero is
6118 * returned. The string is allocated in the SSL context and doesn't have to be
6119 * freed by the caller. NPN is also checked if available since older versions
6120 * of openssl (1.0.1) which are more common in field only support this one.
6121 */
6122static int ssl_sock_get_alpn(const struct connection *conn, const char **str, int *len)
6123{
6124 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6125 return 0;
6126
6127 *str = NULL;
6128
6129#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
6130 SSL_get0_alpn_selected(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6131 if (*str)
6132 return 1;
6133#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006134#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006135 SSL_get0_next_proto_negotiated(conn->xprt_ctx, (const unsigned char **)str, (unsigned *)len);
6136 if (*str)
6137 return 1;
6138#endif
6139 return 0;
6140}
6141
Willy Tarreau7875d092012-09-10 08:20:03 +02006142/***** Below are some sample fetching functions for ACL/patterns *****/
6143
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006144static int
6145smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6146{
6147 struct connection *conn;
6148
6149 conn = objt_conn(smp->sess->origin);
6150 if (!conn || conn->xprt != &ssl_sock)
6151 return 0;
6152
6153 smp->flags = 0;
6154 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006155 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6156 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006157
6158 return 1;
6159}
6160
Emeric Brune64aef12012-09-21 13:15:06 +02006161/* boolean, returns true if client cert was present */
6162static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006163smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006164{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006165 struct connection *conn;
6166
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006167 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006168 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006169 return 0;
6170
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006171 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006172 smp->flags |= SMP_F_MAY_CHANGE;
6173 return 0;
6174 }
6175
6176 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006177 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006178 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & conn->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006179
6180 return 1;
6181}
6182
Emeric Brun43e79582014-10-29 19:03:26 +01006183/* binary, returns a certificate in a binary chunk (der/raw).
6184 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6185 * should be use.
6186 */
6187static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006188smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006189{
6190 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6191 X509 *crt = NULL;
6192 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006193 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006194 struct connection *conn;
6195
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006196 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006197 if (!conn || conn->xprt != &ssl_sock)
6198 return 0;
6199
6200 if (!(conn->flags & CO_FL_CONNECTED)) {
6201 smp->flags |= SMP_F_MAY_CHANGE;
6202 return 0;
6203 }
6204
6205 if (cert_peer)
6206 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6207 else
6208 crt = SSL_get_certificate(conn->xprt_ctx);
6209
6210 if (!crt)
6211 goto out;
6212
6213 smp_trash = get_trash_chunk();
6214 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6215 goto out;
6216
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006217 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006218 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006219 ret = 1;
6220out:
6221 /* SSL_get_peer_certificate, it increase X509 * ref count */
6222 if (cert_peer && crt)
6223 X509_free(crt);
6224 return ret;
6225}
6226
Emeric Brunba841a12014-04-30 17:05:08 +02006227/* binary, returns serial of certificate in a binary chunk.
6228 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6229 * should be use.
6230 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006231static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006232smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006233{
Emeric Brunba841a12014-04-30 17:05:08 +02006234 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006235 X509 *crt = NULL;
6236 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006237 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006238 struct connection *conn;
6239
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006240 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006241 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006242 return 0;
6243
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006244 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006245 smp->flags |= SMP_F_MAY_CHANGE;
6246 return 0;
6247 }
6248
Emeric Brunba841a12014-04-30 17:05:08 +02006249 if (cert_peer)
6250 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6251 else
6252 crt = SSL_get_certificate(conn->xprt_ctx);
6253
Willy Tarreau8d598402012-10-22 17:58:39 +02006254 if (!crt)
6255 goto out;
6256
Willy Tarreau47ca5452012-12-23 20:22:19 +01006257 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006258 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6259 goto out;
6260
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006261 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006262 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006263 ret = 1;
6264out:
Emeric Brunba841a12014-04-30 17:05:08 +02006265 /* SSL_get_peer_certificate, it increase X509 * ref count */
6266 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006267 X509_free(crt);
6268 return ret;
6269}
Emeric Brune64aef12012-09-21 13:15:06 +02006270
Emeric Brunba841a12014-04-30 17:05:08 +02006271/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6272 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6273 * should be use.
6274 */
James Votha051b4a2013-05-14 20:37:59 +02006275static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006276smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006277{
Emeric Brunba841a12014-04-30 17:05:08 +02006278 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006279 X509 *crt = NULL;
6280 const EVP_MD *digest;
6281 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006282 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006283 struct connection *conn;
James Votha051b4a2013-05-14 20:37:59 +02006284
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006285 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006286 if (!conn || conn->xprt != &ssl_sock)
6287 return 0;
6288
6289 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006290 smp->flags |= SMP_F_MAY_CHANGE;
6291 return 0;
6292 }
6293
Emeric Brunba841a12014-04-30 17:05:08 +02006294 if (cert_peer)
6295 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6296 else
6297 crt = SSL_get_certificate(conn->xprt_ctx);
James Votha051b4a2013-05-14 20:37:59 +02006298 if (!crt)
6299 goto out;
6300
6301 smp_trash = get_trash_chunk();
6302 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006303 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6304 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006305
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006306 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006307 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006308 ret = 1;
6309out:
Emeric Brunba841a12014-04-30 17:05:08 +02006310 /* SSL_get_peer_certificate, it increase X509 * ref count */
6311 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006312 X509_free(crt);
6313 return ret;
6314}
6315
Emeric Brunba841a12014-04-30 17:05:08 +02006316/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6317 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6318 * should be use.
6319 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006320static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006321smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006322{
Emeric Brunba841a12014-04-30 17:05:08 +02006323 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006324 X509 *crt = NULL;
6325 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006326 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006327 struct connection *conn;
Emeric Brunce5ad802012-10-22 14:11:22 +02006328
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006329 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006330 if (!conn || conn->xprt != &ssl_sock)
6331 return 0;
6332
6333 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006334 smp->flags |= SMP_F_MAY_CHANGE;
6335 return 0;
6336 }
6337
Emeric Brunba841a12014-04-30 17:05:08 +02006338 if (cert_peer)
6339 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6340 else
6341 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006342 if (!crt)
6343 goto out;
6344
Willy Tarreau47ca5452012-12-23 20:22:19 +01006345 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006346 if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
6347 goto out;
6348
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006349 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006350 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006351 ret = 1;
6352out:
Emeric Brunba841a12014-04-30 17:05:08 +02006353 /* SSL_get_peer_certificate, it increase X509 * ref count */
6354 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006355 X509_free(crt);
6356 return ret;
6357}
6358
Emeric Brunba841a12014-04-30 17:05:08 +02006359/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6360 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6361 * should be use.
6362 */
Emeric Brun87855892012-10-17 17:39:35 +02006363static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006364smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006365{
Emeric Brunba841a12014-04-30 17:05:08 +02006366 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006367 X509 *crt = NULL;
6368 X509_NAME *name;
6369 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006370 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006371 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006372
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006373 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006374 if (!conn || conn->xprt != &ssl_sock)
6375 return 0;
6376
6377 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006378 smp->flags |= SMP_F_MAY_CHANGE;
6379 return 0;
6380 }
6381
Emeric Brunba841a12014-04-30 17:05:08 +02006382 if (cert_peer)
6383 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6384 else
6385 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006386 if (!crt)
6387 goto out;
6388
6389 name = X509_get_issuer_name(crt);
6390 if (!name)
6391 goto out;
6392
Willy Tarreau47ca5452012-12-23 20:22:19 +01006393 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006394 if (args && args[0].type == ARGT_STR) {
6395 int pos = 1;
6396
6397 if (args[1].type == ARGT_SINT)
6398 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006399
6400 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6401 goto out;
6402 }
6403 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6404 goto out;
6405
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006406 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006407 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006408 ret = 1;
6409out:
Emeric Brunba841a12014-04-30 17:05:08 +02006410 /* SSL_get_peer_certificate, it increase X509 * ref count */
6411 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006412 X509_free(crt);
6413 return ret;
6414}
6415
Emeric Brunba841a12014-04-30 17:05:08 +02006416/* string, returns notbefore date in ASN1_UTCTIME format.
6417 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6418 * should be use.
6419 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006420static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006421smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006422{
Emeric Brunba841a12014-04-30 17:05:08 +02006423 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006424 X509 *crt = NULL;
6425 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006426 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006427 struct connection *conn;
6428
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006429 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006430 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006431 return 0;
6432
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006433 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006434 smp->flags |= SMP_F_MAY_CHANGE;
6435 return 0;
6436 }
6437
Emeric Brunba841a12014-04-30 17:05:08 +02006438 if (cert_peer)
6439 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6440 else
6441 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brunce5ad802012-10-22 14:11:22 +02006442 if (!crt)
6443 goto out;
6444
Willy Tarreau47ca5452012-12-23 20:22:19 +01006445 smp_trash = get_trash_chunk();
Emeric Brunce5ad802012-10-22 14:11:22 +02006446 if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
6447 goto out;
6448
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006449 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006450 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006451 ret = 1;
6452out:
Emeric Brunba841a12014-04-30 17:05:08 +02006453 /* SSL_get_peer_certificate, it increase X509 * ref count */
6454 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006455 X509_free(crt);
6456 return ret;
6457}
6458
Emeric Brunba841a12014-04-30 17:05:08 +02006459/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6460 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6461 * should be use.
6462 */
Emeric Brun87855892012-10-17 17:39:35 +02006463static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006464smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006465{
Emeric Brunba841a12014-04-30 17:05:08 +02006466 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006467 X509 *crt = NULL;
6468 X509_NAME *name;
6469 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006470 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006471 struct connection *conn;
Emeric Brun87855892012-10-17 17:39:35 +02006472
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006473 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006474 if (!conn || conn->xprt != &ssl_sock)
6475 return 0;
6476
6477 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006478 smp->flags |= SMP_F_MAY_CHANGE;
6479 return 0;
6480 }
6481
Emeric Brunba841a12014-04-30 17:05:08 +02006482 if (cert_peer)
6483 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6484 else
6485 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun87855892012-10-17 17:39:35 +02006486 if (!crt)
6487 goto out;
6488
6489 name = X509_get_subject_name(crt);
6490 if (!name)
6491 goto out;
6492
Willy Tarreau47ca5452012-12-23 20:22:19 +01006493 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006494 if (args && args[0].type == ARGT_STR) {
6495 int pos = 1;
6496
6497 if (args[1].type == ARGT_SINT)
6498 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006499
6500 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6501 goto out;
6502 }
6503 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6504 goto out;
6505
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006506 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006507 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006508 ret = 1;
6509out:
Emeric Brunba841a12014-04-30 17:05:08 +02006510 /* SSL_get_peer_certificate, it increase X509 * ref count */
6511 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006512 X509_free(crt);
6513 return ret;
6514}
Emeric Brun9143d372012-12-20 15:44:16 +01006515
6516/* integer, returns true if current session use a client certificate */
6517static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006518smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006519{
6520 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006521 struct connection *conn;
Emeric Brun9143d372012-12-20 15:44:16 +01006522
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006523 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006524 if (!conn || conn->xprt != &ssl_sock)
6525 return 0;
6526
6527 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006528 smp->flags |= SMP_F_MAY_CHANGE;
6529 return 0;
6530 }
6531
6532 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006533 crt = SSL_get_peer_certificate(conn->xprt_ctx);
Emeric Brun9143d372012-12-20 15:44:16 +01006534 if (crt) {
6535 X509_free(crt);
6536 }
6537
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006538 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006539 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006540 return 1;
6541}
6542
Emeric Brunba841a12014-04-30 17:05:08 +02006543/* integer, returns the certificate version
6544 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6545 * should be use.
6546 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006547static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006548smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006549{
Emeric Brunba841a12014-04-30 17:05:08 +02006550 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006551 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006552 struct connection *conn;
6553
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006554 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006555 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006556 return 0;
6557
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006558 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006559 smp->flags |= SMP_F_MAY_CHANGE;
6560 return 0;
6561 }
6562
Emeric Brunba841a12014-04-30 17:05:08 +02006563 if (cert_peer)
6564 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6565 else
6566 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006567 if (!crt)
6568 return 0;
6569
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006570 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006571 /* SSL_get_peer_certificate increase X509 * ref count */
6572 if (cert_peer)
6573 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006574 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006575
6576 return 1;
6577}
6578
Emeric Brunba841a12014-04-30 17:05:08 +02006579/* string, returns the certificate's signature algorithm.
6580 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6581 * should be use.
6582 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006583static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006584smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006585{
Emeric Brunba841a12014-04-30 17:05:08 +02006586 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006587 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006588 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006589 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006590 struct connection *conn;
Emeric Brun7f56e742012-10-19 18:15:40 +02006591
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006592 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006593 if (!conn || conn->xprt != &ssl_sock)
6594 return 0;
6595
6596 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006597 smp->flags |= SMP_F_MAY_CHANGE;
6598 return 0;
6599 }
6600
Emeric Brunba841a12014-04-30 17:05:08 +02006601 if (cert_peer)
6602 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6603 else
6604 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun7f56e742012-10-19 18:15:40 +02006605 if (!crt)
6606 return 0;
6607
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006608 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6609 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006610
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006611 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6612 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006613 /* SSL_get_peer_certificate increase X509 * ref count */
6614 if (cert_peer)
6615 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006616 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006617 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006618
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006619 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006620 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006621 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006622 /* SSL_get_peer_certificate increase X509 * ref count */
6623 if (cert_peer)
6624 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006625
6626 return 1;
6627}
6628
Emeric Brunba841a12014-04-30 17:05:08 +02006629/* string, returns the certificate's key algorithm.
6630 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6631 * should be use.
6632 */
Emeric Brun521a0112012-10-22 12:22:55 +02006633static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006634smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006635{
Emeric Brunba841a12014-04-30 17:05:08 +02006636 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006637 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006638 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006639 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006640 struct connection *conn;
Emeric Brun521a0112012-10-22 12:22:55 +02006641
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006642 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006643 if (!conn || conn->xprt != &ssl_sock)
6644 return 0;
6645
6646 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006647 smp->flags |= SMP_F_MAY_CHANGE;
6648 return 0;
6649 }
6650
Emeric Brunba841a12014-04-30 17:05:08 +02006651 if (cert_peer)
6652 crt = SSL_get_peer_certificate(conn->xprt_ctx);
6653 else
6654 crt = SSL_get_certificate(conn->xprt_ctx);
Emeric Brun521a0112012-10-22 12:22:55 +02006655 if (!crt)
6656 return 0;
6657
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006658 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6659 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006660
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006661 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6662 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006663 /* SSL_get_peer_certificate increase X509 * ref count */
6664 if (cert_peer)
6665 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006666 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006667 }
Emeric Brun521a0112012-10-22 12:22:55 +02006668
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006669 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006670 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006671 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006672 if (cert_peer)
6673 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006674
6675 return 1;
6676}
6677
Emeric Brun645ae792014-04-30 14:21:06 +02006678/* boolean, returns true if front conn. transport layer is SSL.
6679 * This function is also usable on backend conn if the fetch keyword 5th
6680 * char is 'b'.
6681 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006682static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006683smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006684{
Emeric Bruneb8def92018-02-19 15:59:48 +01006685 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6686 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006687
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006688 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006689 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006690 return 1;
6691}
6692
Emeric Brun2525b6b2012-10-18 15:59:43 +02006693/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006694static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006695smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006696{
6697#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006698 struct connection *conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006699
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006700 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006701 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006702 conn->xprt_ctx &&
6703 SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006704 return 1;
6705#else
6706 return 0;
6707#endif
6708}
6709
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006710/* boolean, returns true if client session has been resumed.
6711 * This function is also usable on backend conn if the fetch keyword 5th
6712 * char is 'b'.
6713 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006714static int
6715smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
6716{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01006717 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6718 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6719
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006720
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006721 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006722 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02006723 conn->xprt_ctx &&
6724 SSL_session_reused(conn->xprt_ctx);
6725 return 1;
6726}
6727
Emeric Brun645ae792014-04-30 14:21:06 +02006728/* string, returns the used cipher if front conn. transport layer is SSL.
6729 * This function is also usable on backend conn if the fetch keyword 5th
6730 * char is 'b'.
6731 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006732static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006733smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006734{
Emeric Bruneb8def92018-02-19 15:59:48 +01006735 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6736 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Emeric Brun589fcad2012-10-16 14:13:26 +02006737
Willy Tarreaube508f12016-03-10 11:47:01 +01006738 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006739 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006740 return 0;
6741
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006742 smp->data.u.str.area = (char *)SSL_get_cipher_name(conn->xprt_ctx);
6743 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006744 return 0;
6745
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006746 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006747 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006748 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006749
6750 return 1;
6751}
6752
Emeric Brun645ae792014-04-30 14:21:06 +02006753/* integer, returns the algoritm's keysize if front conn. transport layer
6754 * is SSL.
6755 * This function is also usable on backend conn if the fetch keyword 5th
6756 * char is 'b'.
6757 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006758static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006759smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006760{
Emeric Bruneb8def92018-02-19 15:59:48 +01006761 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6762 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006763 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01006764
Emeric Brun589fcad2012-10-16 14:13:26 +02006765 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006766 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02006767 return 0;
6768
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02006769 if (!SSL_get_cipher_bits(conn->xprt_ctx, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006770 return 0;
6771
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006772 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006773 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006774
6775 return 1;
6776}
6777
Emeric Brun645ae792014-04-30 14:21:06 +02006778/* integer, returns the used keysize if front conn. transport layer is SSL.
6779 * This function is also usable on backend conn if the fetch keyword 5th
6780 * char is 'b'.
6781 */
Emeric Brun589fcad2012-10-16 14:13:26 +02006782static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006783smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006784{
Emeric Bruneb8def92018-02-19 15:59:48 +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;
Willy Tarreaube508f12016-03-10 11:47:01 +01006787
Emeric Brun589fcad2012-10-16 14:13:26 +02006788 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006789 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6790 return 0;
6791
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006792 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(conn->xprt_ctx, NULL);
6793 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02006794 return 0;
6795
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006796 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02006797
6798 return 1;
6799}
6800
Bernard Spil13c53f82018-02-15 13:34:58 +01006801#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02006802static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006803smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006804{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006805 struct connection *conn;
6806
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006807 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006808 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006809
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006810 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006811 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6812 return 0;
6813
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006814 smp->data.u.str.area = NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006815 SSL_get0_next_proto_negotiated(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006816 (const unsigned char **)&smp->data.u.str.area,
6817 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02006818
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006819 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02006820 return 0;
6821
6822 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02006823}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02006824#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02006825
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006826#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02006827static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006828smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02006829{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006830 struct connection *conn;
6831
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006832 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006833 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02006834
Willy Tarreaue26bf052015-05-12 10:30:12 +02006835 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006836 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02006837 return 0;
6838
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006839 smp->data.u.str.area = NULL;
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01006840 SSL_get0_alpn_selected(conn->xprt_ctx,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006841 (const unsigned char **)&smp->data.u.str.area,
6842 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02006843
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006844 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02006845 return 0;
6846
6847 return 1;
6848}
6849#endif
6850
Emeric Brun645ae792014-04-30 14:21:06 +02006851/* string, returns the used protocol if front conn. transport layer is SSL.
6852 * This function is also usable on backend conn if the fetch keyword 5th
6853 * char is 'b'.
6854 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02006855static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006856smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02006857{
Emeric Bruneb8def92018-02-19 15:59:48 +01006858 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6859 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaube508f12016-03-10 11:47:01 +01006860
Emeric Brun589fcad2012-10-16 14:13:26 +02006861 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006862 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6863 return 0;
6864
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006865 smp->data.u.str.area = (char *)SSL_get_version(conn->xprt_ctx);
6866 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02006867 return 0;
6868
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006869 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006870 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006871 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02006872
6873 return 1;
6874}
6875
Willy Tarreau87b09662015-04-03 00:22:06 +02006876/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02006877 * This function is also usable on backend conn if the fetch keyword 5th
6878 * char is 'b'.
6879 */
Patrick Hemmer41966772018-04-28 19:15:48 -04006880#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02006881static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006882smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02006883{
Emeric Bruneb8def92018-02-19 15:59:48 +01006884 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6885 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01006886 SSL_SESSION *ssl_sess;
Willy Tarreaube508f12016-03-10 11:47:01 +01006887
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006888 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006889 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02006890
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006891 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6892 return 0;
6893
Willy Tarreau192252e2015-04-04 01:47:55 +02006894 ssl_sess = SSL_get_session(conn->xprt_ctx);
6895 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02006896 return 0;
6897
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006898 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
6899 (unsigned int *)&smp->data.u.str.data);
6900 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02006901 return 0;
6902
6903 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02006904}
Patrick Hemmer41966772018-04-28 19:15:48 -04006905#endif
6906
Emeric Brunfe68f682012-10-16 14:59:28 +02006907
Patrick Hemmere0275472018-04-28 19:15:51 -04006908#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
6909static int
6910smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
6911{
6912 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6913 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
6914 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02006915 struct buffer *data;
Patrick Hemmere0275472018-04-28 19:15:51 -04006916
6917 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6918 return 0;
6919
6920 ssl_sess = SSL_get_session(conn->xprt_ctx);
6921 if (!ssl_sess)
6922 return 0;
6923
6924 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006925 data->data = SSL_SESSION_get_master_key(ssl_sess,
6926 (unsigned char *) data->area,
6927 data->size);
6928 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04006929 return 0;
6930
6931 smp->flags = 0;
6932 smp->data.type = SMP_T_BIN;
6933 smp->data.u.str = *data;
6934
6935 return 1;
6936}
6937#endif
6938
Patrick Hemmer41966772018-04-28 19:15:48 -04006939#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02006940static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006941smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006942{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006943 struct connection *conn;
6944
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006945 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006946 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02006947
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006948 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006949 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6950 return 0;
6951
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006952 smp->data.u.str.area = (char *)SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
6953 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02006954 return 0;
6955
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006956 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02006957 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02006958}
Patrick Hemmer41966772018-04-28 19:15:48 -04006959#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02006960
David Sc1ad52e2014-04-08 18:48:47 -04006961static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006962smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
6963{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006964 struct connection *conn;
6965 struct ssl_capture *capture;
6966
6967 conn = objt_conn(smp->sess->origin);
6968 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
6969 return 0;
6970
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01006971 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006972 if (!capture)
6973 return 0;
6974
6975 smp->flags = SMP_F_CONST;
6976 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006977 smp->data.u.str.area = capture->ciphersuite;
6978 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006979 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006980}
6981
6982static int
6983smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
6984{
Willy Tarreau83061a82018-07-13 11:56:34 +02006985 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006986
6987 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
6988 return 0;
6989
6990 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006991 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01006992 smp->data.type = SMP_T_BIN;
6993 smp->data.u.str = *data;
6994 return 1;
6995}
6996
6997static int
6998smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
6999{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007000 struct connection *conn;
7001 struct ssl_capture *capture;
7002
7003 conn = objt_conn(smp->sess->origin);
7004 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7005 return 0;
7006
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01007007 capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007008 if (!capture)
7009 return 0;
7010
7011 smp->data.type = SMP_T_SINT;
7012 smp->data.u.sint = capture->xxh64;
7013 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007014}
7015
7016static int
7017smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7018{
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007019#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && !defined(LIBRESSL_VERSION_NUMBER)
Willy Tarreau83061a82018-07-13 11:56:34 +02007020 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007021 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007022
7023 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7024 return 0;
7025
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007026 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007027 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007028 const char *str;
7029 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007030 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007031 uint16_t id = (bin[0] << 8) | bin[1];
7032#if defined(OPENSSL_IS_BORINGSSL)
7033 cipher = SSL_get_cipher_by_value(id);
7034#else
7035 struct connection *conn = objt_conn(smp->sess->origin);
7036 cipher = SSL_CIPHER_find(conn->xprt_ctx, bin);
7037#endif
7038 str = SSL_CIPHER_get_name(cipher);
7039 if (!str || strcmp(str, "(NONE)") == 0)
7040 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007041 else
7042 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7043 }
7044 smp->data.type = SMP_T_STR;
7045 smp->data.u.str = *data;
7046 return 1;
7047#else
7048 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7049#endif
7050}
7051
Patrick Hemmer41966772018-04-28 19:15:48 -04007052#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007053static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007054smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007055{
Emeric Bruneb8def92018-02-19 15:59:48 +01007056 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7057 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007058 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007059 struct buffer *finished_trash;
David Sc1ad52e2014-04-08 18:48:47 -04007060
7061 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007062 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7063 return 0;
7064
7065 if (!(conn->flags & CO_FL_CONNECTED)) {
7066 smp->flags |= SMP_F_MAY_CHANGE;
7067 return 0;
7068 }
7069
7070 finished_trash = get_trash_chunk();
7071 if (!SSL_session_reused(conn->xprt_ctx))
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007072 finished_len = SSL_get_peer_finished(conn->xprt_ctx,
7073 finished_trash->area,
7074 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007075 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007076 finished_len = SSL_get_finished(conn->xprt_ctx,
7077 finished_trash->area,
7078 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007079
7080 if (!finished_len)
7081 return 0;
7082
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007083 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007084 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007085 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007086
7087 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007088}
Patrick Hemmer41966772018-04-28 19:15:48 -04007089#endif
David Sc1ad52e2014-04-08 18:48:47 -04007090
Emeric Brun2525b6b2012-10-18 15:59:43 +02007091/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007092static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007093smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007094{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007095 struct connection *conn;
7096
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007097 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007098 if (!conn || conn->xprt != &ssl_sock)
7099 return 0;
7100
7101 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007102 smp->flags = SMP_F_MAY_CHANGE;
7103 return 0;
7104 }
7105
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007106 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007107 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007108 smp->flags = 0;
7109
7110 return 1;
7111}
7112
Emeric Brun2525b6b2012-10-18 15:59:43 +02007113/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007114static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007115smp_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 +02007116{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007117 struct connection *conn;
7118
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007119 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007120 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007121 return 0;
7122
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007123 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007124 smp->flags = SMP_F_MAY_CHANGE;
7125 return 0;
7126 }
7127
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007128 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007129 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007130 smp->flags = 0;
7131
7132 return 1;
7133}
7134
Emeric Brun2525b6b2012-10-18 15:59:43 +02007135/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007136static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007137smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007138{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007139 struct connection *conn;
7140
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007141 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007142 if (!conn || conn->xprt != &ssl_sock)
7143 return 0;
7144
7145 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007146 smp->flags = SMP_F_MAY_CHANGE;
7147 return 0;
7148 }
7149
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007150 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007151 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(conn->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007152 smp->flags = 0;
7153
7154 return 1;
7155}
7156
Emeric Brun2525b6b2012-10-18 15:59:43 +02007157/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007158static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007159smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007160{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007161 struct connection *conn;
7162
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007163 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007164 if (!conn || conn->xprt != &ssl_sock)
7165 return 0;
7166
7167 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007168 smp->flags = SMP_F_MAY_CHANGE;
7169 return 0;
7170 }
7171
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007172 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007173 return 0;
7174
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007175 smp->data.type = SMP_T_SINT;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007176 smp->data.u.sint = (long long int)SSL_get_verify_result(conn->xprt_ctx);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007177 smp->flags = 0;
7178
7179 return 1;
7180}
7181
Emeric Brunfb510ea2012-10-05 12:00:26 +02007182/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007183static 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 +02007184{
7185 if (!*args[cur_arg + 1]) {
7186 if (err)
7187 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7188 return ERR_ALERT | ERR_FATAL;
7189 }
7190
Willy Tarreauef934602016-12-22 23:12:01 +01007191 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7192 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007193 else
7194 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007195
Emeric Brund94b3fe2012-09-20 18:23:56 +02007196 return 0;
7197}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007198static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7199{
7200 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7201}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007202
Christopher Faulet31af49d2015-06-09 17:29:50 +02007203/* parse the "ca-sign-file" bind keyword */
7204static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7205{
7206 if (!*args[cur_arg + 1]) {
7207 if (err)
7208 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7209 return ERR_ALERT | ERR_FATAL;
7210 }
7211
Willy Tarreauef934602016-12-22 23:12:01 +01007212 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7213 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007214 else
7215 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7216
7217 return 0;
7218}
7219
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007220/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007221static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7222{
7223 if (!*args[cur_arg + 1]) {
7224 if (err)
7225 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7226 return ERR_ALERT | ERR_FATAL;
7227 }
7228 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7229 return 0;
7230}
7231
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007232/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007233static 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 +02007234{
7235 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007236 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007237 return ERR_ALERT | ERR_FATAL;
7238 }
7239
Emeric Brun76d88952012-10-05 15:47:31 +02007240 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007241 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007242 return 0;
7243}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007244static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7245{
7246 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7247}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007248/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007249static 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 +02007250{
Willy Tarreau38011032013-08-13 16:59:39 +02007251 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007252
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007253 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007254 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007255 return ERR_ALERT | ERR_FATAL;
7256 }
7257
Willy Tarreauef934602016-12-22 23:12:01 +01007258 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7259 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007260 memprintf(err, "'%s' : path too long", args[cur_arg]);
7261 return ERR_ALERT | ERR_FATAL;
7262 }
Willy Tarreauef934602016-12-22 23:12:01 +01007263 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007264 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007265 return ERR_ALERT | ERR_FATAL;
7266
7267 return 0;
7268 }
7269
Willy Tarreau03209342016-12-22 17:08:28 +01007270 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007271 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007272
7273 return 0;
7274}
7275
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007276/* parse the "crt-list" bind keyword */
7277static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7278{
7279 if (!*args[cur_arg + 1]) {
7280 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7281 return ERR_ALERT | ERR_FATAL;
7282 }
7283
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007284 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007285 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007286 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007287 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007288
7289 return 0;
7290}
7291
Emeric Brunfb510ea2012-10-05 12:00:26 +02007292/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007293static 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 +02007294{
Emeric Brun051cdab2012-10-02 19:25:50 +02007295#ifndef X509_V_FLAG_CRL_CHECK
7296 if (err)
7297 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7298 return ERR_ALERT | ERR_FATAL;
7299#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007300 if (!*args[cur_arg + 1]) {
7301 if (err)
7302 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7303 return ERR_ALERT | ERR_FATAL;
7304 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007305
Willy Tarreauef934602016-12-22 23:12:01 +01007306 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7307 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007308 else
7309 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007310
Emeric Brun2b58d042012-09-20 17:10:03 +02007311 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007312#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007313}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007314static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7315{
7316 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7317}
Emeric Brun2b58d042012-09-20 17:10:03 +02007318
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007319/* parse the "curves" bind keyword keyword */
7320static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7321{
7322#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
7323 if (!*args[cur_arg + 1]) {
7324 if (err)
7325 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7326 return ERR_ALERT | ERR_FATAL;
7327 }
7328 conf->curves = strdup(args[cur_arg + 1]);
7329 return 0;
7330#else
7331 if (err)
7332 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7333 return ERR_ALERT | ERR_FATAL;
7334#endif
7335}
7336static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7337{
7338 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7339}
7340
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007341/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007342static 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 +02007343{
7344#if OPENSSL_VERSION_NUMBER < 0x0090800fL
7345 if (err)
7346 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7347 return ERR_ALERT | ERR_FATAL;
7348#elif defined(OPENSSL_NO_ECDH)
7349 if (err)
7350 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7351 return ERR_ALERT | ERR_FATAL;
7352#else
7353 if (!*args[cur_arg + 1]) {
7354 if (err)
7355 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7356 return ERR_ALERT | ERR_FATAL;
7357 }
7358
7359 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007360
7361 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007362#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007363}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007364static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7365{
7366 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7367}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007368
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007369/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007370static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7371{
7372 int code;
7373 char *p = args[cur_arg + 1];
7374 unsigned long long *ignerr = &conf->crt_ignerr;
7375
7376 if (!*p) {
7377 if (err)
7378 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7379 return ERR_ALERT | ERR_FATAL;
7380 }
7381
7382 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7383 ignerr = &conf->ca_ignerr;
7384
7385 if (strcmp(p, "all") == 0) {
7386 *ignerr = ~0ULL;
7387 return 0;
7388 }
7389
7390 while (p) {
7391 code = atoi(p);
7392 if ((code <= 0) || (code > 63)) {
7393 if (err)
7394 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7395 args[cur_arg], code, args[cur_arg + 1]);
7396 return ERR_ALERT | ERR_FATAL;
7397 }
7398 *ignerr |= 1ULL << code;
7399 p = strchr(p, ',');
7400 if (p)
7401 p++;
7402 }
7403
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007404 return 0;
7405}
7406
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007407/* parse tls_method_options "no-xxx" and "force-xxx" */
7408static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007409{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007410 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007411 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007412 p = strchr(arg, '-');
7413 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007414 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007415 p++;
7416 if (!strcmp(p, "sslv3"))
7417 v = CONF_SSLV3;
7418 else if (!strcmp(p, "tlsv10"))
7419 v = CONF_TLSV10;
7420 else if (!strcmp(p, "tlsv11"))
7421 v = CONF_TLSV11;
7422 else if (!strcmp(p, "tlsv12"))
7423 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007424 else if (!strcmp(p, "tlsv13"))
7425 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007426 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007427 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007428 if (!strncmp(arg, "no-", 3))
7429 methods->flags |= methodVersions[v].flag;
7430 else if (!strncmp(arg, "force-", 6))
7431 methods->min = methods->max = v;
7432 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007433 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007434 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007435 fail:
7436 if (err)
7437 memprintf(err, "'%s' : option not implemented", arg);
7438 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007439}
7440
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007441static 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 +02007442{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007443 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007444}
7445
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007446static 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 +02007447{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007448 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7449}
7450
7451/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7452static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7453{
7454 uint16_t i, v = 0;
7455 char *argv = args[cur_arg + 1];
7456 if (!*argv) {
7457 if (err)
7458 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7459 return ERR_ALERT | ERR_FATAL;
7460 }
7461 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7462 if (!strcmp(argv, methodVersions[i].name))
7463 v = i;
7464 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007465 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007466 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007467 return ERR_ALERT | ERR_FATAL;
7468 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007469 if (!strcmp("ssl-min-ver", args[cur_arg]))
7470 methods->min = v;
7471 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7472 methods->max = v;
7473 else {
7474 if (err)
7475 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7476 return ERR_ALERT | ERR_FATAL;
7477 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007478 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007479}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007480
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007481static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7482{
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02007483#if (OPENSSL_VERSION_NUMBER < 0x10101000L) || !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007484 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 +02007485#endif
7486 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7487}
7488
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007489static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7490{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007491 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007492}
7493
7494static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7495{
7496 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7497}
7498
Emeric Brun2d0c4822012-10-02 13:45:20 +02007499/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007500static 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 +02007501{
Emeric Brun89675492012-10-05 13:48:26 +02007502 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007503 return 0;
7504}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007505
Olivier Houchardc2aae742017-09-22 18:26:28 +02007506/* parse the "allow-0rtt" bind keyword */
7507static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7508{
7509 conf->early_data = 1;
7510 return 0;
7511}
7512
7513static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7514{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007515 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007516 return 0;
7517}
7518
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007519/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007520static 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 +02007521{
Bernard Spil13c53f82018-02-15 13:34:58 +01007522#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007523 char *p1, *p2;
7524
7525 if (!*args[cur_arg + 1]) {
7526 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7527 return ERR_ALERT | ERR_FATAL;
7528 }
7529
7530 free(conf->npn_str);
7531
Willy Tarreau3724da12016-02-12 17:11:12 +01007532 /* the NPN string is built as a suite of (<len> <name>)*,
7533 * so we reuse each comma to store the next <len> and need
7534 * one more for the end of the string.
7535 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007536 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007537 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007538 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7539
7540 /* replace commas with the name length */
7541 p1 = conf->npn_str;
7542 p2 = p1 + 1;
7543 while (1) {
7544 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7545 if (!p2)
7546 p2 = p1 + 1 + strlen(p1 + 1);
7547
7548 if (p2 - (p1 + 1) > 255) {
7549 *p2 = '\0';
7550 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7551 return ERR_ALERT | ERR_FATAL;
7552 }
7553
7554 *p1 = p2 - (p1 + 1);
7555 p1 = p2;
7556
7557 if (!*p2)
7558 break;
7559
7560 *(p2++) = '\0';
7561 }
7562 return 0;
7563#else
7564 if (err)
7565 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7566 return ERR_ALERT | ERR_FATAL;
7567#endif
7568}
7569
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007570static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7571{
7572 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7573}
7574
Willy Tarreauab861d32013-04-02 02:30:41 +02007575/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007576static 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 +02007577{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007578#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007579 char *p1, *p2;
7580
7581 if (!*args[cur_arg + 1]) {
7582 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7583 return ERR_ALERT | ERR_FATAL;
7584 }
7585
7586 free(conf->alpn_str);
7587
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007588 /* the ALPN string is built as a suite of (<len> <name>)*,
7589 * so we reuse each comma to store the next <len> and need
7590 * one more for the end of the string.
7591 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007592 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007593 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007594 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7595
7596 /* replace commas with the name length */
7597 p1 = conf->alpn_str;
7598 p2 = p1 + 1;
7599 while (1) {
7600 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7601 if (!p2)
7602 p2 = p1 + 1 + strlen(p1 + 1);
7603
7604 if (p2 - (p1 + 1) > 255) {
7605 *p2 = '\0';
7606 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7607 return ERR_ALERT | ERR_FATAL;
7608 }
7609
7610 *p1 = p2 - (p1 + 1);
7611 p1 = p2;
7612
7613 if (!*p2)
7614 break;
7615
7616 *(p2++) = '\0';
7617 }
7618 return 0;
7619#else
7620 if (err)
7621 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7622 return ERR_ALERT | ERR_FATAL;
7623#endif
7624}
7625
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007626static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7627{
7628 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7629}
7630
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007631/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007632static 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 +02007633{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007634 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007635 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007636
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007637 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7638 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007639 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007640 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7641 if (!conf->ssl_conf.ssl_methods.min)
7642 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7643 if (!conf->ssl_conf.ssl_methods.max)
7644 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007645
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007646 return 0;
7647}
7648
Lukas Tribus53ae85c2017-05-04 15:45:40 +00007649/* parse the "prefer-client-ciphers" bind keyword */
7650static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7651{
7652 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
7653 return 0;
7654}
7655
Christopher Faulet31af49d2015-06-09 17:29:50 +02007656/* parse the "generate-certificates" bind keyword */
7657static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7658{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01007659#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02007660 conf->generate_certs = 1;
7661#else
7662 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
7663 err && *err ? *err : "");
7664#endif
7665 return 0;
7666}
7667
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007668/* parse the "strict-sni" bind keyword */
7669static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7670{
7671 conf->strict_sni = 1;
7672 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007673}
7674
7675/* parse the "tls-ticket-keys" bind keyword */
7676static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7677{
7678#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
7679 FILE *f;
7680 int i = 0;
7681 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007682 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007683
7684 if (!*args[cur_arg + 1]) {
7685 if (err)
7686 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
7687 return ERR_ALERT | ERR_FATAL;
7688 }
7689
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007690 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007691 if (keys_ref) {
7692 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007693 conf->keys_ref = keys_ref;
7694 return 0;
7695 }
7696
Vincent Bernat02779b62016-04-03 13:48:43 +02007697 keys_ref = malloc(sizeof(*keys_ref));
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007698 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(struct tls_sess_key));
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007699
7700 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
7701 if (err)
7702 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
7703 return ERR_ALERT | ERR_FATAL;
7704 }
7705
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007706 keys_ref->filename = strdup(args[cur_arg + 1]);
7707
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007708 while (fgets(thisline, sizeof(thisline), f) != NULL) {
7709 int len = strlen(thisline);
7710 /* Strip newline characters from the end */
7711 if(thisline[len - 1] == '\n')
7712 thisline[--len] = 0;
7713
7714 if(thisline[len - 1] == '\r')
7715 thisline[--len] = 0;
7716
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007717 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 +01007718 if (err)
7719 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02007720 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007721 return ERR_ALERT | ERR_FATAL;
7722 }
7723 i++;
7724 }
7725
7726 if (i < TLS_TICKETS_NO) {
7727 if (err)
7728 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 +02007729 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007730 return ERR_ALERT | ERR_FATAL;
7731 }
7732
7733 fclose(f);
7734
7735 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01007736 i -= 2;
7737 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007738 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02007739 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01007740 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02007741 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007742
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02007743 LIST_ADD(&tlskeys_reference, &keys_ref->list);
7744
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007745 return 0;
7746#else
7747 if (err)
7748 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
7749 return ERR_ALERT | ERR_FATAL;
7750#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01007751}
7752
Emeric Brund94b3fe2012-09-20 18:23:56 +02007753/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007754static 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 +02007755{
7756 if (!*args[cur_arg + 1]) {
7757 if (err)
7758 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
7759 return ERR_ALERT | ERR_FATAL;
7760 }
7761
7762 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007763 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007764 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007765 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007766 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01007767 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007768 else {
7769 if (err)
7770 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
7771 args[cur_arg], args[cur_arg + 1]);
7772 return ERR_ALERT | ERR_FATAL;
7773 }
7774
7775 return 0;
7776}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007777static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7778{
7779 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
7780}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007781
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02007782/* parse the "no-ca-names" bind keyword */
7783static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7784{
7785 conf->no_ca_names = 1;
7786 return 0;
7787}
7788static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7789{
7790 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
7791}
7792
Willy Tarreau92faadf2012-10-10 23:04:25 +02007793/************** "server" keywords ****************/
7794
Emeric Brunef42d922012-10-11 16:11:36 +02007795/* parse the "ca-file" server keyword */
7796static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7797{
7798 if (!*args[*cur_arg + 1]) {
7799 if (err)
7800 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
7801 return ERR_ALERT | ERR_FATAL;
7802 }
7803
Willy Tarreauef934602016-12-22 23:12:01 +01007804 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7805 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007806 else
7807 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
7808
7809 return 0;
7810}
7811
Olivier Houchard9130a962017-10-17 17:33:43 +02007812/* parse the "check-sni" server keyword */
7813static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7814{
7815 if (!*args[*cur_arg + 1]) {
7816 if (err)
7817 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
7818 return ERR_ALERT | ERR_FATAL;
7819 }
7820
7821 newsrv->check.sni = strdup(args[*cur_arg + 1]);
7822 if (!newsrv->check.sni) {
7823 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
7824 return ERR_ALERT | ERR_FATAL;
7825 }
7826 return 0;
7827
7828}
7829
Willy Tarreau92faadf2012-10-10 23:04:25 +02007830/* parse the "check-ssl" server keyword */
7831static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7832{
7833 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007834 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7835 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
7836 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007837 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
7838 if (!newsrv->ssl_ctx.methods.min)
7839 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
7840 if (!newsrv->ssl_ctx.methods.max)
7841 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
7842
Willy Tarreau92faadf2012-10-10 23:04:25 +02007843 return 0;
7844}
7845
7846/* parse the "ciphers" server keyword */
7847static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7848{
7849 if (!*args[*cur_arg + 1]) {
7850 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
7851 return ERR_ALERT | ERR_FATAL;
7852 }
7853
7854 free(newsrv->ssl_ctx.ciphers);
7855 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
7856 return 0;
7857}
7858
Emeric Brunef42d922012-10-11 16:11:36 +02007859/* parse the "crl-file" server keyword */
7860static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7861{
7862#ifndef X509_V_FLAG_CRL_CHECK
7863 if (err)
7864 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
7865 return ERR_ALERT | ERR_FATAL;
7866#else
7867 if (!*args[*cur_arg + 1]) {
7868 if (err)
7869 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
7870 return ERR_ALERT | ERR_FATAL;
7871 }
7872
Willy Tarreauef934602016-12-22 23:12:01 +01007873 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
7874 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007875 else
7876 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
7877
7878 return 0;
7879#endif
7880}
7881
Emeric Bruna7aa3092012-10-26 12:58:00 +02007882/* parse the "crt" server keyword */
7883static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7884{
7885 if (!*args[*cur_arg + 1]) {
7886 if (err)
7887 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
7888 return ERR_ALERT | ERR_FATAL;
7889 }
7890
Willy Tarreauef934602016-12-22 23:12:01 +01007891 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01007892 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02007893 else
7894 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
7895
7896 return 0;
7897}
Emeric Brunef42d922012-10-11 16:11:36 +02007898
Frédéric Lécaille340ae602017-03-13 10:38:04 +01007899/* parse the "no-check-ssl" server keyword */
7900static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7901{
7902 newsrv->check.use_ssl = 0;
7903 free(newsrv->ssl_ctx.ciphers);
7904 newsrv->ssl_ctx.ciphers = NULL;
7905 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
7906 return 0;
7907}
7908
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01007909/* parse the "no-send-proxy-v2-ssl" server keyword */
7910static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7911{
7912 newsrv->pp_opts &= ~SRV_PP_V2;
7913 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7914 return 0;
7915}
7916
7917/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
7918static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7919{
7920 newsrv->pp_opts &= ~SRV_PP_V2;
7921 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
7922 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
7923 return 0;
7924}
7925
Frédéric Lécaillee381d762017-03-13 11:54:17 +01007926/* parse the "no-ssl" server keyword */
7927static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7928{
7929 newsrv->use_ssl = 0;
7930 free(newsrv->ssl_ctx.ciphers);
7931 newsrv->ssl_ctx.ciphers = NULL;
7932 return 0;
7933}
7934
Olivier Houchard522eea72017-11-03 16:27:47 +01007935/* parse the "allow-0rtt" server keyword */
7936static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7937{
7938 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
7939 return 0;
7940}
7941
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01007942/* parse the "no-ssl-reuse" server keyword */
7943static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7944{
7945 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
7946 return 0;
7947}
7948
Emeric Brunf9c5c472012-10-11 15:28:34 +02007949/* parse the "no-tls-tickets" server keyword */
7950static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7951{
7952 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
7953 return 0;
7954}
David Safb76832014-05-08 23:42:08 -04007955/* parse the "send-proxy-v2-ssl" server keyword */
7956static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7957{
7958 newsrv->pp_opts |= SRV_PP_V2;
7959 newsrv->pp_opts |= SRV_PP_V2_SSL;
7960 return 0;
7961}
7962
7963/* parse the "send-proxy-v2-ssl-cn" server keyword */
7964static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7965{
7966 newsrv->pp_opts |= SRV_PP_V2;
7967 newsrv->pp_opts |= SRV_PP_V2_SSL;
7968 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
7969 return 0;
7970}
Emeric Brunf9c5c472012-10-11 15:28:34 +02007971
Willy Tarreau732eac42015-07-09 11:40:25 +02007972/* parse the "sni" server keyword */
7973static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7974{
7975#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
7976 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
7977 return ERR_ALERT | ERR_FATAL;
7978#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007979 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02007980
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007981 arg = args[*cur_arg + 1];
7982 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02007983 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
7984 return ERR_ALERT | ERR_FATAL;
7985 }
7986
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01007987 free(newsrv->sni_expr);
7988 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02007989
Willy Tarreau732eac42015-07-09 11:40:25 +02007990 return 0;
7991#endif
7992}
7993
Willy Tarreau92faadf2012-10-10 23:04:25 +02007994/* parse the "ssl" server keyword */
7995static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7996{
7997 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01007998 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
7999 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008000 return 0;
8001}
8002
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008003/* parse the "ssl-reuse" server keyword */
8004static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8005{
8006 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8007 return 0;
8008}
8009
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008010/* parse the "tls-tickets" server keyword */
8011static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8012{
8013 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8014 return 0;
8015}
8016
Emeric Brunef42d922012-10-11 16:11:36 +02008017/* parse the "verify" server keyword */
8018static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8019{
8020 if (!*args[*cur_arg + 1]) {
8021 if (err)
8022 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8023 return ERR_ALERT | ERR_FATAL;
8024 }
8025
8026 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008027 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008028 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008029 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008030 else {
8031 if (err)
8032 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8033 args[*cur_arg], args[*cur_arg + 1]);
8034 return ERR_ALERT | ERR_FATAL;
8035 }
8036
Evan Broderbe554312013-06-27 00:05:25 -07008037 return 0;
8038}
8039
8040/* parse the "verifyhost" server keyword */
8041static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8042{
8043 if (!*args[*cur_arg + 1]) {
8044 if (err)
8045 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8046 return ERR_ALERT | ERR_FATAL;
8047 }
8048
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008049 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008050 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8051
Emeric Brunef42d922012-10-11 16:11:36 +02008052 return 0;
8053}
8054
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008055/* parse the "ssl-default-bind-options" keyword in global section */
8056static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8057 struct proxy *defpx, const char *file, int line,
8058 char **err) {
8059 int i = 1;
8060
8061 if (*(args[i]) == 0) {
8062 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8063 return -1;
8064 }
8065 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008066 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008067 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008068 else if (!strcmp(args[i], "prefer-client-ciphers"))
8069 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008070 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8071 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8072 i++;
8073 else {
8074 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8075 return -1;
8076 }
8077 }
8078 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008079 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8080 return -1;
8081 }
8082 i++;
8083 }
8084 return 0;
8085}
8086
8087/* parse the "ssl-default-server-options" keyword in global section */
8088static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8089 struct proxy *defpx, const char *file, int line,
8090 char **err) {
8091 int i = 1;
8092
8093 if (*(args[i]) == 0) {
8094 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8095 return -1;
8096 }
8097 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008098 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008099 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008100 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8101 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8102 i++;
8103 else {
8104 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8105 return -1;
8106 }
8107 }
8108 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008109 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8110 return -1;
8111 }
8112 i++;
8113 }
8114 return 0;
8115}
8116
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008117/* parse the "ca-base" / "crt-base" keywords in global section.
8118 * Returns <0 on alert, >0 on warning, 0 on success.
8119 */
8120static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8121 struct proxy *defpx, const char *file, int line,
8122 char **err)
8123{
8124 char **target;
8125
Willy Tarreauef934602016-12-22 23:12:01 +01008126 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008127
8128 if (too_many_args(1, args, err, NULL))
8129 return -1;
8130
8131 if (*target) {
8132 memprintf(err, "'%s' already specified.", args[0]);
8133 return -1;
8134 }
8135
8136 if (*(args[1]) == 0) {
8137 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8138 return -1;
8139 }
8140 *target = strdup(args[1]);
8141 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008142}
8143
8144/* parse the "ssl-mode-async" keyword in global section.
8145 * Returns <0 on alert, >0 on warning, 0 on success.
8146 */
8147static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8148 struct proxy *defpx, const char *file, int line,
8149 char **err)
8150{
Emmanuel Hocdete966e4e2017-10-24 18:11:48 +02008151#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008152 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008153 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008154 return 0;
8155#else
8156 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8157 return -1;
8158#endif
8159}
8160
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008161#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008162static int ssl_check_async_engine_count(void) {
8163 int err_code = 0;
8164
Emeric Brun3854e012017-05-17 20:42:48 +02008165 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008166 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008167 err_code = ERR_ABORT;
8168 }
8169 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008170}
8171
Grant Zhang872f9c22017-01-21 01:10:18 +00008172/* parse the "ssl-engine" keyword in global section.
8173 * Returns <0 on alert, >0 on warning, 0 on success.
8174 */
8175static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8176 struct proxy *defpx, const char *file, int line,
8177 char **err)
8178{
8179 char *algo;
8180 int ret = -1;
8181
8182 if (*(args[1]) == 0) {
8183 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8184 return ret;
8185 }
8186
8187 if (*(args[2]) == 0) {
8188 /* if no list of algorithms is given, it defaults to ALL */
8189 algo = strdup("ALL");
8190 goto add_engine;
8191 }
8192
8193 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8194 if (strcmp(args[2], "algo") != 0) {
8195 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8196 return ret;
8197 }
8198
8199 if (*(args[3]) == 0) {
8200 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8201 return ret;
8202 }
8203 algo = strdup(args[3]);
8204
8205add_engine:
8206 if (ssl_init_single_engine(args[1], algo)==0) {
8207 openssl_engines_initialized++;
8208 ret = 0;
8209 }
8210 free(algo);
8211 return ret;
8212}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008213#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008214
Willy Tarreauf22e9682016-12-21 23:23:19 +01008215/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8216 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8217 */
8218static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8219 struct proxy *defpx, const char *file, int line,
8220 char **err)
8221{
8222 char **target;
8223
Willy Tarreauef934602016-12-22 23:12:01 +01008224 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008225
8226 if (too_many_args(1, args, err, NULL))
8227 return -1;
8228
8229 if (*(args[1]) == 0) {
8230 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8231 return -1;
8232 }
8233
8234 free(*target);
8235 *target = strdup(args[1]);
8236 return 0;
8237}
8238
Willy Tarreau9ceda382016-12-21 23:13:03 +01008239/* parse various global tune.ssl settings consisting in positive integers.
8240 * Returns <0 on alert, >0 on warning, 0 on success.
8241 */
8242static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8243 struct proxy *defpx, const char *file, int line,
8244 char **err)
8245{
8246 int *target;
8247
8248 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8249 target = &global.tune.sslcachesize;
8250 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008251 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008252 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008253 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008254 else if (strcmp(args[0], "maxsslconn") == 0)
8255 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008256 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8257 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008258 else {
8259 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8260 return -1;
8261 }
8262
8263 if (too_many_args(1, args, err, NULL))
8264 return -1;
8265
8266 if (*(args[1]) == 0) {
8267 memprintf(err, "'%s' expects an integer argument.", args[0]);
8268 return -1;
8269 }
8270
8271 *target = atoi(args[1]);
8272 if (*target < 0) {
8273 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8274 return -1;
8275 }
8276 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008277}
8278
8279static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8280 struct proxy *defpx, const char *file, int line,
8281 char **err)
8282{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008283 int ret;
8284
8285 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8286 if (ret != 0)
8287 return ret;
8288
Willy Tarreaubafbe012017-11-24 17:34:44 +01008289 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008290 memprintf(err, "'%s' is already configured.", args[0]);
8291 return -1;
8292 }
8293
Willy Tarreaubafbe012017-11-24 17:34:44 +01008294 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8295 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008296 memprintf(err, "Out of memory error.");
8297 return -1;
8298 }
8299 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008300}
8301
8302/* parse "ssl.force-private-cache".
8303 * Returns <0 on alert, >0 on warning, 0 on success.
8304 */
8305static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8306 struct proxy *defpx, const char *file, int line,
8307 char **err)
8308{
8309 if (too_many_args(0, args, err, NULL))
8310 return -1;
8311
Willy Tarreauef934602016-12-22 23:12:01 +01008312 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008313 return 0;
8314}
8315
8316/* parse "ssl.lifetime".
8317 * Returns <0 on alert, >0 on warning, 0 on success.
8318 */
8319static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8320 struct proxy *defpx, const char *file, int line,
8321 char **err)
8322{
8323 const char *res;
8324
8325 if (too_many_args(1, args, err, NULL))
8326 return -1;
8327
8328 if (*(args[1]) == 0) {
8329 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8330 return -1;
8331 }
8332
Willy Tarreauef934602016-12-22 23:12:01 +01008333 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008334 if (res) {
8335 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8336 return -1;
8337 }
8338 return 0;
8339}
8340
8341#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008342/* parse "ssl-dh-param-file".
8343 * Returns <0 on alert, >0 on warning, 0 on success.
8344 */
8345static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8346 struct proxy *defpx, const char *file, int line,
8347 char **err)
8348{
8349 if (too_many_args(1, args, err, NULL))
8350 return -1;
8351
8352 if (*(args[1]) == 0) {
8353 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8354 return -1;
8355 }
8356
8357 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8358 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8359 return -1;
8360 }
8361 return 0;
8362}
8363
Willy Tarreau9ceda382016-12-21 23:13:03 +01008364/* parse "ssl.default-dh-param".
8365 * Returns <0 on alert, >0 on warning, 0 on success.
8366 */
8367static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8368 struct proxy *defpx, const char *file, int line,
8369 char **err)
8370{
8371 if (too_many_args(1, args, err, NULL))
8372 return -1;
8373
8374 if (*(args[1]) == 0) {
8375 memprintf(err, "'%s' expects an integer argument.", args[0]);
8376 return -1;
8377 }
8378
Willy Tarreauef934602016-12-22 23:12:01 +01008379 global_ssl.default_dh_param = atoi(args[1]);
8380 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008381 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8382 return -1;
8383 }
8384 return 0;
8385}
8386#endif
8387
8388
William Lallemand32af2032016-10-29 18:09:35 +02008389/* This function is used with TLS ticket keys management. It permits to browse
8390 * each reference. The variable <getnext> must contain the current node,
8391 * <end> point to the root node.
8392 */
8393#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8394static inline
8395struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8396{
8397 struct tls_keys_ref *ref = getnext;
8398
8399 while (1) {
8400
8401 /* Get next list entry. */
8402 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8403
8404 /* If the entry is the last of the list, return NULL. */
8405 if (&ref->list == end)
8406 return NULL;
8407
8408 return ref;
8409 }
8410}
8411
8412static inline
8413struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8414{
8415 int id;
8416 char *error;
8417
8418 /* If the reference starts by a '#', this is numeric id. */
8419 if (reference[0] == '#') {
8420 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8421 id = strtol(reference + 1, &error, 10);
8422 if (*error != '\0')
8423 return NULL;
8424
8425 /* Perform the unique id lookup. */
8426 return tlskeys_ref_lookupid(id);
8427 }
8428
8429 /* Perform the string lookup. */
8430 return tlskeys_ref_lookup(reference);
8431}
8432#endif
8433
8434
8435#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8436
8437static int cli_io_handler_tlskeys_files(struct appctx *appctx);
8438
8439static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
8440 return cli_io_handler_tlskeys_files(appctx);
8441}
8442
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008443/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
8444 * (next index to be dumped), and cli.p0 (next key reference).
8445 */
William Lallemand32af2032016-10-29 18:09:35 +02008446static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
8447
8448 struct stream_interface *si = appctx->owner;
8449
8450 switch (appctx->st2) {
8451 case STAT_ST_INIT:
8452 /* Display the column headers. If the message cannot be sent,
8453 * quit the fucntion with returning 0. The function is called
8454 * later and restart at the state "STAT_ST_INIT".
8455 */
8456 chunk_reset(&trash);
8457
8458 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
8459 chunk_appendf(&trash, "# id secret\n");
8460 else
8461 chunk_appendf(&trash, "# id (file)\n");
8462
Willy Tarreau06d80a92017-10-19 14:32:15 +02008463 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008464 si_applet_cant_put(si);
8465 return 0;
8466 }
8467
William Lallemand32af2032016-10-29 18:09:35 +02008468 /* Now, we start the browsing of the references lists.
8469 * Note that the following call to LIST_ELEM return bad pointer. The only
8470 * available field of this pointer is <list>. It is used with the function
8471 * tlskeys_list_get_next() for retruning the first available entry
8472 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008473 if (appctx->ctx.cli.p0 == NULL) {
8474 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
8475 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008476 }
8477
8478 appctx->st2 = STAT_ST_LIST;
8479 /* fall through */
8480
8481 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008482 while (appctx->ctx.cli.p0) {
8483 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02008484
8485 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008486 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02008487 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008488
8489 if (appctx->ctx.cli.i1 == 0)
8490 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
8491
William Lallemand32af2032016-10-29 18:09:35 +02008492 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01008493 int head;
8494
8495 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
8496 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008497 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02008498 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02008499
8500 chunk_reset(t2);
8501 /* should never fail here because we dump only a key in the t2 buffer */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02008502 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
8503 sizeof(struct tls_sess_key),
8504 t2->area, t2->size);
8505 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
8506 t2->area);
William Lallemand32af2032016-10-29 18:09:35 +02008507
Willy Tarreau06d80a92017-10-19 14:32:15 +02008508 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008509 /* let's try again later from this stream. We add ourselves into
8510 * this stream's users so that it can remove us upon termination.
8511 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01008512 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
William Lallemand32af2032016-10-29 18:09:35 +02008513 si_applet_cant_put(si);
8514 return 0;
8515 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008516 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02008517 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01008518 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008519 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008520 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02008521 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02008522 /* let's try again later from this stream. We add ourselves into
8523 * this stream's users so that it can remove us upon termination.
8524 */
8525 si_applet_cant_put(si);
8526 return 0;
8527 }
8528
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008529 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02008530 break;
8531
8532 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008533 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02008534 }
8535
8536 appctx->st2 = STAT_ST_FIN;
8537 /* fall through */
8538
8539 default:
8540 appctx->st2 = STAT_ST_FIN;
8541 return 1;
8542 }
8543 return 0;
8544}
8545
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008546/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008547static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008548{
William Lallemand32af2032016-10-29 18:09:35 +02008549 /* no parameter, shows only file list */
8550 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008551 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008552 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008553 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008554 }
8555
8556 if (args[2][0] == '*') {
8557 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008558 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02008559 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008560 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
8561 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008562 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008563 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008564 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008565 return 1;
8566 }
8567 }
William Lallemand32af2032016-10-29 18:09:35 +02008568 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01008569 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02008570}
8571
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008572static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008573{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008574 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008575 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008576
William Lallemand32af2032016-10-29 18:09:35 +02008577 /* Expect two parameters: the filename and the new new TLS key in encoding */
8578 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008579 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008580 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 +01008581 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008582 return 1;
8583 }
8584
Willy Tarreauf5f26e82016-12-16 18:47:27 +01008585 ref = tlskeys_ref_lookup_ref(args[3]);
8586 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008587 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008588 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008589 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008590 return 1;
8591 }
8592
Willy Tarreau1c913e42018-08-22 05:26:57 +02008593 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
8594 if (ret != sizeof(struct tls_sess_key)) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008595 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008596 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008597 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008598 return 1;
8599 }
Willy Tarreau1c913e42018-08-22 05:26:57 +02008600 trash.data = ret;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008601 ssl_sock_update_tlskey_ref(ref, &trash);
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008602 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008603 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008604 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008605 return 1;
8606
8607}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008608#endif
William Lallemand32af2032016-10-29 18:09:35 +02008609
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02008610static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02008611{
8612#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
8613 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02008614 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008615
8616 if (!payload)
8617 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02008618
8619 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008620 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008621 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008622 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008623 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008624 return 1;
8625 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02008626
8627 /* remove \r and \n from the payload */
8628 for (i = 0, j = 0; payload[i]; i++) {
8629 if (payload[i] == '\r' || payload[i] == '\n')
8630 continue;
8631 payload[j++] = payload[i];
8632 }
8633 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02008634
Willy Tarreau1c913e42018-08-22 05:26:57 +02008635 ret = base64dec(payload, j, trash.area, trash.size);
8636 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008637 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008638 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008639 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008640 return 1;
8641 }
8642
Willy Tarreau1c913e42018-08-22 05:26:57 +02008643 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02008644 if (ssl_sock_update_ocsp_response(&trash, &err)) {
8645 if (err) {
8646 memprintf(&err, "%s.\n", err);
8647 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008648 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02008649 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02008650 else {
8651 appctx->ctx.cli.severity = LOG_ERR;
8652 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
8653 appctx->st0 = CLI_ST_PRINT;
8654 }
William Lallemand32af2032016-10-29 18:09:35 +02008655 return 1;
8656 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008657 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01008658 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01008659 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008660 return 1;
8661#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02008662 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02008663 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 +01008664 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02008665 return 1;
8666#endif
8667
8668}
8669
8670/* register cli keywords */
8671static struct cli_kw_list cli_kws = {{ },{
8672#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8673 { { "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 +02008674 { { "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 +02008675#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008676 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02008677 { { NULL }, NULL, NULL, NULL }
8678}};
8679
8680
Willy Tarreau7875d092012-09-10 08:20:03 +02008681/* Note: must not be declared <const> as its list will be overwritten.
8682 * Please take care of keeping this list alphabetically sorted.
8683 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008684static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02008685 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008686 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Emeric Brun645ae792014-04-30 14:21:06 +02008687 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brun74f7ffa2018-02-19 16:14:12 +01008688 { "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 +02008689 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02008690 { "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 +02008691 { "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 -04008692#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02008693 { "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 -04008694#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008695#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8696 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
8697#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008698 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8699 { "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 +01008700 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008701 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008702 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8703 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8704 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8705 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8706 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8707 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8708 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8709 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008710 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008711 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
8712 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01008713 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02008714 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8715 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8716 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8717 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8718 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8719 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
8720 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02008721 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008722 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008723 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008724 { "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 +01008725 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01008726 { "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 +02008727 { "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 +01008728 { "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 +02008729 { "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 +01008730#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008731 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02008732#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008733#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008734 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02008735#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008736 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008737#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02008738 { "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 -04008739#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02008740 { "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 -04008741#if OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008742 { "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 -04008743#endif
Patrick Hemmere0275472018-04-28 19:15:51 -04008744#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
8745 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8746#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04008747#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01008748 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04008749#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008750 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8751 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
8752 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
8753 { "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 +02008754 { NULL, NULL, 0, 0, 0 },
8755}};
8756
8757/* Note: must not be declared <const> as its list will be overwritten.
8758 * Please take care of keeping this list alphabetically sorted.
8759 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02008760static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01008761 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
8762 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01008763 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02008764}};
8765
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008766/* Note: must not be declared <const> as its list will be overwritten.
8767 * Please take care of keeping this list alphabetically sorted, doing so helps
8768 * all code contributors.
8769 * Optional keywords are also declared with a NULL ->parse() function so that
8770 * the config parser can report an appropriate error when a known keyword was
8771 * not enabled.
8772 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008773static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008774 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008775 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8776 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8777 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8778 { "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 +01008779 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008780 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008781 { "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 +01008782 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008783 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
8784 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008785 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
8786 { NULL, NULL, 0 },
8787};
8788
Willy Tarreau51fb7652012-09-18 18:24:39 +02008789static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02008790 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008791 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
8792 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
8793 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
8794 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
8795 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
8796 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
8797 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
8798 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
8799 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
8800 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
8801 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
8802 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
8803 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
8804 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
8805 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
8806 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008807 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008808 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008809 { "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 +02008810 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
8811 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
8812 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
8813 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008814 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008815 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
8816 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008817 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
8818 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008819 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
8820 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
8821 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
8822 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
8823 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008824 { NULL, NULL, 0 },
8825}};
Emeric Brun46591952012-05-18 15:47:34 +02008826
Willy Tarreau92faadf2012-10-10 23:04:25 +02008827/* Note: must not be declared <const> as its list will be overwritten.
8828 * Please take care of keeping this list alphabetically sorted, doing so helps
8829 * all code contributors.
8830 * Optional keywords are also declared with a NULL ->parse() function so that
8831 * the config parser can report an appropriate error when a known keyword was
8832 * not enabled.
8833 */
8834static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01008835 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008836 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard9130a962017-10-17 17:33:43 +02008837 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008838 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
8839 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
8840 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
8841 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
8842 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
8843 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
8844 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
8845 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
8846 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
8847 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
8848 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
8849 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
8850 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
8851 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
8852 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
8853 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
8854 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
8855 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
8856 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
8857 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
8858 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
8859 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
8860 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
8861 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
8862 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
8863 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
8864 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
8865 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
8866 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
8867 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02008868 { NULL, NULL, 0, 0 },
8869}};
8870
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008871static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008872 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
8873 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008874 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008875 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
8876 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01008877#ifndef OPENSSL_NO_DH
8878 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
8879#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008880 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008881#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008882 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008883#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01008884 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
8885#ifndef OPENSSL_NO_DH
8886 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
8887#endif
8888 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
8889 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
8890 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
8891 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008892 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01008893 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
8894 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008895 { 0, NULL, NULL },
8896}};
8897
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02008898/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01008899static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02008900 .snd_buf = ssl_sock_from_buf,
8901 .rcv_buf = ssl_sock_to_buf,
Olivier Houchard6ff20392018-07-17 18:46:31 +02008902 .subscribe = conn_subscribe,
Emeric Brun46591952012-05-18 15:47:34 +02008903 .rcv_pipe = NULL,
8904 .snd_pipe = NULL,
8905 .shutr = NULL,
8906 .shutw = ssl_sock_shutw,
8907 .close = ssl_sock_close,
8908 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01008909 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01008910 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01008911 .prepare_srv = ssl_sock_prepare_srv_ctx,
8912 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01008913 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01008914 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02008915};
8916
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008917enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
8918 struct session *sess, struct stream *s, int flags)
8919{
8920 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008921 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008922
8923 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008924 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008925
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008926 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008927 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01008928 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02008929 s->req.flags |= CF_READ_NULL;
8930 return ACT_RET_YIELD;
8931 }
8932 }
8933 return (ACT_RET_CONT);
8934}
8935
8936static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
8937{
8938 rule->action_ptr = ssl_action_wait_for_hs;
8939
8940 return ACT_RET_PRS_OK;
8941}
8942
8943static struct action_kw_list http_req_actions = {ILH, {
8944 { "wait-for-handshake", ssl_parse_wait_for_hs },
8945 { /* END */ }
8946}};
8947
Daniel Jakots54ffb912015-11-06 20:02:41 +01008948#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008949
8950static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8951{
8952 if (ptr) {
8953 chunk_destroy(ptr);
8954 free(ptr);
8955 }
8956}
8957
8958#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008959static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
8960{
Willy Tarreaubafbe012017-11-24 17:34:44 +01008961 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01008962}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008963
Emeric Brun46591952012-05-18 15:47:34 +02008964__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02008965static void __ssl_sock_init(void)
8966{
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008967 char *ptr;
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02008968 int i;
Willy Tarreauc2c0b612016-12-21 19:23:20 +01008969
Emeric Brun46591952012-05-18 15:47:34 +02008970 STACK_OF(SSL_COMP)* cm;
8971
Willy Tarreauef934602016-12-22 23:12:01 +01008972 if (global_ssl.listen_default_ciphers)
8973 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
8974 if (global_ssl.connect_default_ciphers)
8975 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau610f04b2014-02-13 11:36:41 +01008976
Willy Tarreau13e14102016-12-22 20:25:26 +01008977 xprt_register(XPRT_SSL, &ssl_sock);
Emeric Brun46591952012-05-18 15:47:34 +02008978 SSL_library_init();
8979 cm = SSL_COMP_get_compression_methods();
8980 sk_SSL_COMP_zero(cm);
Emeric Brun821bb9b2017-06-15 16:37:39 +02008981#ifdef USE_THREAD
8982 ssl_locking_init();
8983#endif
Daniel Jakots54ffb912015-11-06 20:02:41 +01008984#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01008985 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
8986#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02008987 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02008988 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 +01008989 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Willy Tarreau7875d092012-09-10 08:20:03 +02008990 sample_register_fetches(&sample_fetch_keywords);
8991 acl_register_keywords(&acl_kws);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008992 bind_register_keywords(&bind_kws);
Willy Tarreau92faadf2012-10-10 23:04:25 +02008993 srv_register_keywords(&srv_kws);
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008994 cfg_register_keywords(&cfg_kws);
William Lallemand32af2032016-10-29 18:09:35 +02008995 cli_register_kw(&cli_kws);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008996#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00008997 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008998 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008999#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009000#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9001 hap_register_post_check(tlskeys_finalize_config);
9002#endif
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009003
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009004 ptr = NULL;
9005 memprintf(&ptr, "Built with OpenSSL version : "
9006#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009007 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009008#else /* OPENSSL_IS_BORINGSSL */
9009 OPENSSL_VERSION_TEXT
9010 "\nRunning on OpenSSL version : %s%s",
9011 SSLeay_version(SSLEAY_VERSION),
9012 ((OPENSSL_VERSION_NUMBER ^ SSLeay()) >> 8) ? " (VERSIONS DIFFER!)" : "");
9013#endif
9014 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
9015#if OPENSSL_VERSION_NUMBER < 0x00907000L
9016 "no (library version too old)"
9017#elif defined(OPENSSL_NO_TLSEXT)
9018 "no (disabled via OPENSSL_NO_TLSEXT)"
9019#else
9020 "yes"
9021#endif
9022 "", ptr);
9023
9024 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9025#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9026 "yes"
9027#else
9028#ifdef OPENSSL_NO_TLSEXT
9029 "no (because of OPENSSL_NO_TLSEXT)"
9030#else
9031 "no (version might be too old, 0.9.8f min needed)"
9032#endif
9033#endif
9034 "", ptr);
9035
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009036 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9037 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9038 if (methodVersions[i].option)
9039 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009040
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009041 hap_register_build_opts(ptr, 1);
9042
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009043 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9044 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
Remi Gacogne4f902b82015-05-28 16:23:00 +02009045
9046#ifndef OPENSSL_NO_DH
9047 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Grant Zhang872f9c22017-01-21 01:10:18 +00009048 hap_register_post_deinit(ssl_free_dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009049#endif
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009050#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009051 hap_register_post_deinit(ssl_free_engines);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009052#endif
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02009053 /* Load SSL string for the verbose & debug mode. */
9054 ERR_load_SSL_strings();
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009055
9056 http_req_keywords_register(&http_req_actions);
Emeric Brun46591952012-05-18 15:47:34 +02009057}
9058
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009059#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009060void ssl_free_engines(void) {
9061 struct ssl_engine_list *wl, *wlb;
9062 /* free up engine list */
9063 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9064 ENGINE_finish(wl->e);
9065 ENGINE_free(wl->e);
9066 LIST_DEL(&wl->list);
9067 free(wl);
9068 }
9069}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009070#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009071
Remi Gacogned3a23c32015-05-28 16:39:47 +02009072#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009073void ssl_free_dh(void) {
9074 if (local_dh_1024) {
9075 DH_free(local_dh_1024);
9076 local_dh_1024 = NULL;
9077 }
9078 if (local_dh_2048) {
9079 DH_free(local_dh_2048);
9080 local_dh_2048 = NULL;
9081 }
9082 if (local_dh_4096) {
9083 DH_free(local_dh_4096);
9084 local_dh_4096 = NULL;
9085 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009086 if (global_dh) {
9087 DH_free(global_dh);
9088 global_dh = NULL;
9089 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009090}
9091#endif
9092
9093__attribute__((destructor))
9094static void __ssl_sock_deinit(void)
9095{
9096#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009097 if (ssl_ctx_lru_tree) {
9098 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009099 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009100 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009101#endif
9102
9103 ERR_remove_state(0);
9104 ERR_free_strings();
9105
9106 EVP_cleanup();
9107
9108#if OPENSSL_VERSION_NUMBER >= 0x00907000L
9109 CRYPTO_cleanup_all_ex_data();
9110#endif
9111}
9112
9113
Emeric Brun46591952012-05-18 15:47:34 +02009114/*
9115 * Local variables:
9116 * c-indent-level: 8
9117 * c-basic-offset: 8
9118 * End:
9119 */