blob: e774b9be8c787c9bc11d01a55a9eba6f2e62270c [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
Willy Tarreau8d164dc2019-05-10 09:35:00 +020026/* Note: do NOT include openssl/xxx.h here, do it in openssl-compat.h */
Emeric Brun46591952012-05-18 15:47:34 +020027#define _GNU_SOURCE
Emeric Brunfc0421f2012-09-07 17:30:07 +020028#include <ctype.h>
29#include <dirent.h>
Emeric Brun46591952012-05-18 15:47:34 +020030#include <errno.h>
31#include <fcntl.h>
32#include <stdio.h>
33#include <stdlib.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020034#include <string.h>
35#include <unistd.h>
Emeric Brun46591952012-05-18 15:47:34 +020036
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/types.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020040#include <netdb.h>
Emeric Brun46591952012-05-18 15:47:34 +020041#include <netinet/tcp.h>
42
Christopher Faulet31af49d2015-06-09 17:29:50 +020043#include <import/lru.h>
44#include <import/xxhash.h>
45
Emeric Brun46591952012-05-18 15:47:34 +020046#include <common/buffer.h>
Willy Tarreau843b7cb2018-07-13 10:54:26 +020047#include <common/chunk.h>
Emeric Brun46591952012-05-18 15:47:34 +020048#include <common/compat.h>
49#include <common/config.h>
50#include <common/debug.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020051#include <common/errors.h>
Willy Tarreau0108d902018-11-25 19:14:37 +010052#include <common/initcall.h>
Willy Tarreau55994562019-05-09 14:52:44 +020053#include <common/openssl-compat.h>
Emeric Brun46591952012-05-18 15:47:34 +020054#include <common/standard.h>
55#include <common/ticks.h>
56#include <common/time.h>
Emeric Brun2c86cbf2014-10-30 15:56:50 +010057#include <common/cfgparse.h>
Nenad Merdanovic05552d42015-02-27 19:56:49 +010058#include <common/base64.h>
Emeric Brun46591952012-05-18 15:47:34 +020059
Emeric Brunfc0421f2012-09-07 17:30:07 +020060#include <ebsttree.h>
61
William Lallemand32af2032016-10-29 18:09:35 +020062#include <types/applet.h>
63#include <types/cli.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020064#include <types/global.h>
65#include <types/ssl_sock.h>
William Lallemand32af2032016-10-29 18:09:35 +020066#include <types/stats.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020067
Willy Tarreau7875d092012-09-10 08:20:03 +020068#include <proto/acl.h>
69#include <proto/arg.h>
William Lallemand32af2032016-10-29 18:09:35 +020070#include <proto/channel.h>
Emeric Brun46591952012-05-18 15:47:34 +020071#include <proto/connection.h>
William Lallemand32af2032016-10-29 18:09:35 +020072#include <proto/cli.h>
Emeric Brun46591952012-05-18 15:47:34 +020073#include <proto/fd.h>
74#include <proto/freq_ctr.h>
75#include <proto/frontend.h>
Willy Tarreau61c112a2018-10-02 16:43:32 +020076#include <proto/http_rules.h>
Willy Tarreau79eeafa2012-09-14 07:53:05 +020077#include <proto/listener.h>
Thierry FOURNIERed66c292013-11-28 11:05:19 +010078#include <proto/pattern.h>
Christopher Faulet31af49d2015-06-09 17:29:50 +020079#include <proto/proto_tcp.h>
Olivier Houchardccaa7de2017-10-02 11:51:03 +020080#include <proto/proto_http.h>
Willy Tarreau92faadf2012-10-10 23:04:25 +020081#include <proto/server.h>
William Lallemand32af2032016-10-29 18:09:35 +020082#include <proto/stream_interface.h>
Emeric Brun46591952012-05-18 15:47:34 +020083#include <proto/log.h>
Emeric Brun94324a42012-10-11 14:00:19 +020084#include <proto/proxy.h>
Emeric Brunfc0421f2012-09-07 17:30:07 +020085#include <proto/shctx.h>
Emeric Brun46591952012-05-18 15:47:34 +020086#include <proto/ssl_sock.h>
Willy Tarreau9ad7bd42015-04-03 19:19:59 +020087#include <proto/stream.h>
Emeric Brun46591952012-05-18 15:47:34 +020088#include <proto/task.h>
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010089#include <proto/vars.h>
Emeric Brun46591952012-05-18 15:47:34 +020090
Willy Tarreau9356dac2019-05-10 09:22:53 +020091/* ***** READ THIS before adding code here! *****
92 *
93 * Due to API incompatibilities between multiple OpenSSL versions and their
94 * derivatives, it's often tempting to add macros to (re-)define certain
95 * symbols. Please do not do this here, and do it in common/openssl-compat.h
96 * exclusively so that the whole code consistently uses the same macros.
97 *
98 * Whenever possible if a macro is missing in certain versions, it's better
99 * to conditionally define it in openssl-compat.h than using lots of ifdefs.
100 */
101
Willy Tarreau518cedd2014-02-17 15:43:01 +0100102/* Warning, these are bits, not integers! */
Emeric Brune64aef12012-09-21 13:15:06 +0200103#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
Emeric Brund8b2bb52014-01-28 15:43:53 +0100104#define SSL_SOCK_ST_FL_16K_WBFSIZE 0x00000002
Willy Tarreau518cedd2014-02-17 15:43:01 +0100105#define SSL_SOCK_SEND_UNLIMITED 0x00000004
Emeric Brun29f037d2014-04-25 19:05:36 +0200106#define SSL_SOCK_RECV_HEARTBEAT 0x00000008
107
Emeric Brunf282a812012-09-21 15:27:54 +0200108/* bits 0xFFFF0000 are reserved to store verify errors */
109
110/* Verify errors macros */
111#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
112#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
113#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
114
115#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
116#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
117#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
Emeric Brune64aef12012-09-21 13:15:06 +0200118
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200119/* ssl_methods flags for ssl options */
120#define MC_SSL_O_ALL 0x0000
121#define MC_SSL_O_NO_SSLV3 0x0001 /* disable SSLv3 */
122#define MC_SSL_O_NO_TLSV10 0x0002 /* disable TLSv10 */
123#define MC_SSL_O_NO_TLSV11 0x0004 /* disable TLSv11 */
124#define MC_SSL_O_NO_TLSV12 0x0008 /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200125#define MC_SSL_O_NO_TLSV13 0x0010 /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200126
127/* ssl_methods versions */
128enum {
129 CONF_TLSV_NONE = 0,
130 CONF_TLSV_MIN = 1,
131 CONF_SSLV3 = 1,
132 CONF_TLSV10 = 2,
133 CONF_TLSV11 = 3,
134 CONF_TLSV12 = 4,
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +0200135 CONF_TLSV13 = 5,
136 CONF_TLSV_MAX = 5,
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200137};
138
Emeric Brun850efd52014-01-29 12:24:34 +0100139/* server and bind verify method, it uses a global value as default */
140enum {
141 SSL_SOCK_VERIFY_DEFAULT = 0,
142 SSL_SOCK_VERIFY_REQUIRED = 1,
143 SSL_SOCK_VERIFY_OPTIONAL = 2,
144 SSL_SOCK_VERIFY_NONE = 3,
145};
146
William Lallemand3f85c9a2017-10-09 16:30:50 +0200147
Willy Tarreau71b734c2014-01-28 15:19:44 +0100148int sslconns = 0;
149int totalsslconns = 0;
Willy Tarreaud9f5cca2016-12-22 21:08:52 +0100150static struct xprt_ops ssl_sock;
Emeric Brunece0c332017-12-06 13:51:49 +0100151int nb_engines = 0;
Emeric Brune1f38db2012-09-03 20:36:47 +0200152
Willy Tarreauef934602016-12-22 23:12:01 +0100153static struct {
154 char *crt_base; /* base directory path for certificates */
155 char *ca_base; /* base directory path for CAs and CRLs */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000156 int async; /* whether we use ssl async mode */
Willy Tarreauef934602016-12-22 23:12:01 +0100157
158 char *listen_default_ciphers;
159 char *connect_default_ciphers;
Willy Tarreau5db847a2019-05-09 14:13:35 +0200160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200161 char *listen_default_ciphersuites;
162 char *connect_default_ciphersuites;
163#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100164 int listen_default_ssloptions;
165 int connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200166 struct tls_version_filter listen_default_sslmethods;
167 struct tls_version_filter connect_default_sslmethods;
Willy Tarreauef934602016-12-22 23:12:01 +0100168
169 int private_cache; /* Force to use a private session cache even if nbproc > 1 */
170 unsigned int life_time; /* SSL session lifetime in seconds */
171 unsigned int max_record; /* SSL max record size */
172 unsigned int default_dh_param; /* SSL maximum DH parameter size */
173 int ctx_cache; /* max number of entries in the ssl_ctx cache. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100174 int capture_cipherlist; /* Size of the cipherlist buffer. */
Willy Tarreauef934602016-12-22 23:12:01 +0100175} global_ssl = {
176#ifdef LISTEN_DEFAULT_CIPHERS
177 .listen_default_ciphers = LISTEN_DEFAULT_CIPHERS,
178#endif
179#ifdef CONNECT_DEFAULT_CIPHERS
180 .connect_default_ciphers = CONNECT_DEFAULT_CIPHERS,
181#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +0200182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +0200183#ifdef LISTEN_DEFAULT_CIPHERSUITES
184 .listen_default_ciphersuites = LISTEN_DEFAULT_CIPHERSUITES,
185#endif
186#ifdef CONNECT_DEFAULT_CIPHERSUITES
187 .connect_default_ciphersuites = CONNECT_DEFAULT_CIPHERSUITES,
188#endif
189#endif
Willy Tarreauef934602016-12-22 23:12:01 +0100190 .listen_default_ssloptions = BC_SSL_O_NONE,
191 .connect_default_ssloptions = SRV_SSL_O_NONE,
192
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +0200193 .listen_default_sslmethods.flags = MC_SSL_O_ALL,
194 .listen_default_sslmethods.min = CONF_TLSV_NONE,
195 .listen_default_sslmethods.max = CONF_TLSV_NONE,
196 .connect_default_sslmethods.flags = MC_SSL_O_ALL,
197 .connect_default_sslmethods.min = CONF_TLSV_NONE,
198 .connect_default_sslmethods.max = CONF_TLSV_NONE,
199
Willy Tarreauef934602016-12-22 23:12:01 +0100200#ifdef DEFAULT_SSL_MAX_RECORD
201 .max_record = DEFAULT_SSL_MAX_RECORD,
202#endif
203 .default_dh_param = SSL_DEFAULT_DH_PARAM,
204 .ctx_cache = DEFAULT_SSL_CTX_CACHE,
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100205 .capture_cipherlist = 0,
Willy Tarreauef934602016-12-22 23:12:01 +0100206};
207
Olivier Houcharda8955d52019-04-07 22:00:38 +0200208static BIO_METHOD *ha_meth;
209
Olivier Houchard66ab4982019-02-26 18:37:15 +0100210struct ssl_sock_ctx {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200211 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100212 SSL *ssl;
Olivier Houcharda8955d52019-04-07 22:00:38 +0200213 BIO *bio;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100214 struct xprt_ops *xprt;
215 void *xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100216 int xprt_st; /* transport layer state, initialized to zero */
217 int tmp_early_data; /* 1st byte of early data, if any */
218 int sent_early_data; /* Amount of early data we sent so far */
219
Olivier Houchard66ab4982019-02-26 18:37:15 +0100220};
221
222DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
223
Olivier Houcharda8955d52019-04-07 22:00:38 +0200224/* Methods to implement OpenSSL BIO */
225static int ha_ssl_write(BIO *h, const char *buf, int num)
226{
227 struct buffer tmpbuf;
228 struct ssl_sock_ctx *ctx;
229 int ret;
230
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200231#if HA_OPENSSL_VERSION_NUMBER < 0x10100000
Olivier Houchard66a7b332019-04-18 15:58:15 +0200232 ctx = h->ptr;
233#else
Olivier Houcharda8955d52019-04-07 22:00:38 +0200234 ctx = BIO_get_data(h);
Olivier Houchard66a7b332019-04-18 15:58:15 +0200235#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +0200236 tmpbuf.size = num;
237 tmpbuf.area = (void *)(uintptr_t)buf;
238 tmpbuf.data = num;
239 tmpbuf.head = 0;
240 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200241 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200242 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200243 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200244 } else if (ret == 0)
245 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200246 return ret;
247}
248
249static int ha_ssl_gets(BIO *h, char *buf, int size)
250{
251
252 return 0;
253}
254
255static int ha_ssl_puts(BIO *h, const char *str)
256{
257
258 return ha_ssl_write(h, str, strlen(str));
259}
260
261static int ha_ssl_read(BIO *h, char *buf, int size)
262{
263 struct buffer tmpbuf;
264 struct ssl_sock_ctx *ctx;
265 int ret;
266
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200267#if HA_OPENSSL_VERSION_NUMBER < 0x10100000
Olivier Houchard66a7b332019-04-18 15:58:15 +0200268 ctx = h->ptr;
269#else
Olivier Houcharda8955d52019-04-07 22:00:38 +0200270 ctx = BIO_get_data(h);
Olivier Houchard66a7b332019-04-18 15:58:15 +0200271#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +0200272 tmpbuf.size = size;
273 tmpbuf.area = buf;
274 tmpbuf.data = 0;
275 tmpbuf.head = 0;
276 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200277 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200278 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200279 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200280 } else if (ret == 0)
281 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200282
283 return ret;
284}
285
286static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
287{
288 int ret = 0;
289 switch (cmd) {
290 case BIO_CTRL_DUP:
291 case BIO_CTRL_FLUSH:
292 ret = 1;
293 break;
294 }
295 return ret;
296}
297
298static int ha_ssl_new(BIO *h)
299{
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200300#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Olivier Houchard66a7b332019-04-18 15:58:15 +0200301 h->init = 1;
302 h->ptr = NULL;
303#else
Olivier Houcharda8955d52019-04-07 22:00:38 +0200304 BIO_set_init(h, 1);
305 BIO_set_data(h, NULL);
Olivier Houchard66a7b332019-04-18 15:58:15 +0200306#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +0200307 BIO_clear_flags(h, ~0);
308 return 1;
309}
310
311static int ha_ssl_free(BIO *data)
312{
313
314 return 1;
315}
316
317
Willy Tarreau5db847a2019-05-09 14:13:35 +0200318#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100319
Emeric Brun821bb9b2017-06-15 16:37:39 +0200320static HA_RWLOCK_T *ssl_rwlocks;
321
322
323unsigned long ssl_id_function(void)
324{
325 return (unsigned long)tid;
326}
327
328void ssl_locking_function(int mode, int n, const char * file, int line)
329{
330 if (mode & CRYPTO_LOCK) {
331 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100332 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200333 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100334 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200335 }
336 else {
337 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100338 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200339 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100340 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200341 }
342}
343
344static int ssl_locking_init(void)
345{
346 int i;
347
348 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
349 if (!ssl_rwlocks)
350 return -1;
351
352 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100353 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354
355 CRYPTO_set_id_callback(ssl_id_function);
356 CRYPTO_set_locking_callback(ssl_locking_function);
357
358 return 0;
359}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100360
Emeric Brun821bb9b2017-06-15 16:37:39 +0200361#endif
362
363
364
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100365/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100366struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100367 unsigned long long int xxh64;
368 unsigned char ciphersuite_len;
369 char ciphersuite[0];
370};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100371struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100372static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200373static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100374
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100375static int ssl_pkey_info_index = -1;
376
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200377#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
378struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
379#endif
380
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200381#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000382static unsigned int openssl_engines_initialized;
383struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
384struct ssl_engine_list {
385 struct list list;
386 ENGINE *e;
387};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200388#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000389
Remi Gacogne8de54152014-07-15 11:36:40 +0200390#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200391static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200392static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200393static DH *local_dh_1024 = NULL;
394static DH *local_dh_2048 = NULL;
395static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100396static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200397#endif /* OPENSSL_NO_DH */
398
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100399#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200400/* X509V3 Extensions that will be added on generated certificates */
401#define X509V3_EXT_SIZE 5
402static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
403 "basicConstraints",
404 "nsComment",
405 "subjectKeyIdentifier",
406 "authorityKeyIdentifier",
407 "keyUsage",
408};
409static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
410 "CA:FALSE",
411 "\"OpenSSL Generated Certificate\"",
412 "hash",
413 "keyid,issuer:always",
414 "nonRepudiation,digitalSignature,keyEncipherment"
415};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200416/* LRU cache to store generated certificate */
417static struct lru64_head *ssl_ctx_lru_tree = NULL;
418static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200419static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100420__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200421
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200422#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
423
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100424static struct ssl_bind_kw ssl_bind_kws[];
425
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200426#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500427/* The order here matters for picking a default context,
428 * keep the most common keytype at the bottom of the list
429 */
430const char *SSL_SOCK_KEYTYPE_NAMES[] = {
431 "dsa",
432 "ecdsa",
433 "rsa"
434};
435#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100436#else
437#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500438#endif
439
William Lallemandc3cd35f2017-11-28 11:04:43 +0100440static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100441static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
442
443#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
444
445#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
446 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
447
448#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
449 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200450
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100451/*
452 * This function gives the detail of the SSL error. It is used only
453 * if the debug mode and the verbose mode are activated. It dump all
454 * the SSL error until the stack was empty.
455 */
456static forceinline void ssl_sock_dump_errors(struct connection *conn)
457{
458 unsigned long ret;
459
460 if (unlikely(global.mode & MODE_DEBUG)) {
461 while(1) {
462 ret = ERR_get_error();
463 if (ret == 0)
464 return;
465 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200466 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100467 ERR_func_error_string(ret), ERR_reason_error_string(ret));
468 }
469 }
470}
471
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200472#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
yanbzhube2774d2015-12-10 15:07:30 -0500473/*
474 * struct alignment works here such that the key.key is the same as key_data
475 * Do not change the placement of key_data
476 */
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200477struct certificate_ocsp {
478 struct ebmb_node key;
479 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
Willy Tarreau83061a82018-07-13 11:56:34 +0200480 struct buffer response;
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200481 long expire;
482};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200483
yanbzhube2774d2015-12-10 15:07:30 -0500484struct ocsp_cbk_arg {
485 int is_single;
486 int single_kt;
487 union {
488 struct certificate_ocsp *s_ocsp;
489 /*
490 * m_ocsp will have multiple entries dependent on key type
491 * Entry 0 - DSA
492 * Entry 1 - ECDSA
493 * Entry 2 - RSA
494 */
495 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
496 };
497};
498
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200499#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000500static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
501{
502 int err_code = ERR_ABORT;
503 ENGINE *engine;
504 struct ssl_engine_list *el;
505
506 /* grab the structural reference to the engine */
507 engine = ENGINE_by_id(engine_id);
508 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100509 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000510 goto fail_get;
511 }
512
513 if (!ENGINE_init(engine)) {
514 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100515 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000516 goto fail_init;
517 }
518
519 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100520 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000521 goto fail_set_method;
522 }
523
524 el = calloc(1, sizeof(*el));
525 el->e = engine;
526 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100527 nb_engines++;
528 if (global_ssl.async)
529 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000530 return 0;
531
532fail_set_method:
533 /* release the functional reference from ENGINE_init() */
534 ENGINE_finish(engine);
535
536fail_init:
537 /* release the structural reference from ENGINE_by_id() */
538 ENGINE_free(engine);
539
540fail_get:
541 return err_code;
542}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200543#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000544
Willy Tarreau5db847a2019-05-09 14:13:35 +0200545#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200546/*
547 * openssl async fd handler
548 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200549void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000550{
551 struct connection *conn = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000552
Emeric Brun3854e012017-05-17 20:42:48 +0200553 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000554 * to poll this fd until it is requested
555 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000556 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000557 fd_cant_recv(fd);
558
559 /* crypto engine is available, let's notify the associated
560 * connection that it can pursue its processing.
561 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000562 __conn_sock_want_recv(conn);
563 __conn_sock_want_send(conn);
564 conn_update_sock_polling(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000565}
566
Emeric Brun3854e012017-05-17 20:42:48 +0200567/*
568 * openssl async delayed SSL_free handler
569 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200570void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571{
572 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200573 OSSL_ASYNC_FD all_fd[32];
574 size_t num_all_fds = 0;
575 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000576
Emeric Brun3854e012017-05-17 20:42:48 +0200577 /* We suppose that the async job for a same SSL *
578 * are serialized. So if we are awake it is
579 * because the running job has just finished
580 * and we can remove all async fds safely
581 */
582 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
583 if (num_all_fds > 32) {
584 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
585 return;
586 }
587
588 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
589 for (i=0 ; i < num_all_fds ; i++)
590 fd_remove(all_fd[i]);
591
592 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000593 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100594 _HA_ATOMIC_SUB(&sslconns, 1);
595 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000596}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000597/*
Emeric Brun3854e012017-05-17 20:42:48 +0200598 * function used to manage a returned SSL_ERROR_WANT_ASYNC
599 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000600 */
Willy Tarreau0e492e22019-04-15 21:25:03 +0200601static inline void ssl_async_process_fds(struct connection *conn, SSL *ssl)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000602{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100603 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200604 OSSL_ASYNC_FD del_fd[32];
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000605 size_t num_add_fds = 0;
606 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200607 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000608
609 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
610 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200611 if (num_add_fds > 32 || num_del_fds > 32) {
612 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 +0000613 return;
614 }
615
Emeric Brun3854e012017-05-17 20:42:48 +0200616 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000617
Emeric Brun3854e012017-05-17 20:42:48 +0200618 /* We remove unused fds from the fdtab */
619 for (i=0 ; i < num_del_fds ; i++)
620 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000621
Emeric Brun3854e012017-05-17 20:42:48 +0200622 /* We add new fds to the fdtab */
623 for (i=0 ; i < num_add_fds ; i++) {
Willy Tarreaua9786b62018-01-25 07:22:13 +0100624 fd_insert(add_fd[i], conn, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000625 }
626
Emeric Brun3854e012017-05-17 20:42:48 +0200627 num_add_fds = 0;
628 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
629 if (num_add_fds > 32) {
630 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
631 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000632 }
Emeric Brun3854e012017-05-17 20:42:48 +0200633
634 /* We activate the polling for all known async fds */
635 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000636 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200637 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000638 /* To ensure that the fd cache won't be used
639 * We'll prefer to catch a real RD event
640 * because handling an EAGAIN on this fd will
641 * result in a context switch and also
642 * some engines uses a fd in blocking mode.
643 */
644 fd_cant_recv(add_fd[i]);
645 }
Emeric Brun3854e012017-05-17 20:42:48 +0200646
647 /* We must also prevent the conn_handler
648 * to be called until a read event was
649 * polled on an async fd
650 */
651 __conn_sock_stop_both(conn);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000652}
653#endif
654
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200655/*
656 * This function returns the number of seconds elapsed
657 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
658 * date presented un ASN1_GENERALIZEDTIME.
659 *
660 * In parsing error case, it returns -1.
661 */
662static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
663{
664 long epoch;
665 char *p, *end;
666 const unsigned short month_offset[12] = {
667 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
668 };
669 int year, month;
670
671 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
672
673 p = (char *)d->data;
674 end = p + d->length;
675
676 if (end - p < 4) return -1;
677 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
678 p += 4;
679 if (end - p < 2) return -1;
680 month = 10 * (p[0] - '0') + p[1] - '0';
681 if (month < 1 || month > 12) return -1;
682 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
683 We consider leap years and the current month (<marsh or not) */
684 epoch = ( ((year - 1970) * 365)
685 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
686 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
687 + month_offset[month-1]
688 ) * 24 * 60 * 60;
689 p += 2;
690 if (end - p < 2) return -1;
691 /* Add the number of seconds of completed days of current month */
692 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
693 p += 2;
694 if (end - p < 2) return -1;
695 /* Add the completed hours of the current day */
696 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
697 p += 2;
698 if (end - p < 2) return -1;
699 /* Add the completed minutes of the current hour */
700 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
701 p += 2;
702 if (p == end) return -1;
703 /* Test if there is available seconds */
704 if (p[0] < '0' || p[0] > '9')
705 goto nosec;
706 if (end - p < 2) return -1;
707 /* Add the seconds of the current minute */
708 epoch += 10 * (p[0] - '0') + p[1] - '0';
709 p += 2;
710 if (p == end) return -1;
711 /* Ignore seconds float part if present */
712 if (p[0] == '.') {
713 do {
714 if (++p == end) return -1;
715 } while (p[0] >= '0' && p[0] <= '9');
716 }
717
718nosec:
719 if (p[0] == 'Z') {
720 if (end - p != 1) return -1;
721 return epoch;
722 }
723 else if (p[0] == '+') {
724 if (end - p != 5) return -1;
725 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700726 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 +0200727 }
728 else if (p[0] == '-') {
729 if (end - p != 5) return -1;
730 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700731 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 +0200732 }
733
734 return -1;
735}
736
Emeric Brun1d3865b2014-06-20 15:37:32 +0200737static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200738
739/* This function starts to check if the OCSP response (in DER format) contained
740 * in chunk 'ocsp_response' is valid (else exits on error).
741 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
742 * contained in the OCSP Response and exits on error if no match.
743 * If it's a valid OCSP Response:
744 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
745 * pointed by 'ocsp'.
746 * If 'ocsp' is NULL, the function looks up into the OCSP response's
747 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
748 * from the response) and exits on error if not found. Finally, If an OCSP response is
749 * already present in the container, it will be overwritten.
750 *
751 * Note: OCSP response containing more than one OCSP Single response is not
752 * considered valid.
753 *
754 * Returns 0 on success, 1 in error case.
755 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200756static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
757 struct certificate_ocsp *ocsp,
758 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200759{
760 OCSP_RESPONSE *resp;
761 OCSP_BASICRESP *bs = NULL;
762 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200763 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200764 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200765 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200766 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200767 int reason;
768 int ret = 1;
769
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200770 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
771 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200772 if (!resp) {
773 memprintf(err, "Unable to parse OCSP response");
774 goto out;
775 }
776
777 rc = OCSP_response_status(resp);
778 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
779 memprintf(err, "OCSP response status not successful");
780 goto out;
781 }
782
783 bs = OCSP_response_get1_basic(resp);
784 if (!bs) {
785 memprintf(err, "Failed to get basic response from OCSP Response");
786 goto out;
787 }
788
789 count_sr = OCSP_resp_count(bs);
790 if (count_sr > 1) {
791 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
792 goto out;
793 }
794
795 sr = OCSP_resp_get0(bs, 0);
796 if (!sr) {
797 memprintf(err, "Failed to get OCSP single response");
798 goto out;
799 }
800
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200801 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
802
Emeric Brun4147b2e2014-06-16 18:36:30 +0200803 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200804 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200805 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200806 goto out;
807 }
808
Emeric Brun13a6b482014-06-20 15:44:34 +0200809 if (!nextupd) {
810 memprintf(err, "OCSP single response: missing nextupdate");
811 goto out;
812 }
813
Emeric Brunc8b27b62014-06-19 14:16:17 +0200814 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200815 if (!rc) {
816 memprintf(err, "OCSP single response: no longer valid.");
817 goto out;
818 }
819
820 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200821 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200822 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
823 goto out;
824 }
825 }
826
827 if (!ocsp) {
828 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
829 unsigned char *p;
830
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200831 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200832 if (!rc) {
833 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
834 goto out;
835 }
836
837 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
838 memprintf(err, "OCSP single response: Certificate ID too long");
839 goto out;
840 }
841
842 p = key;
843 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200844 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200845 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
846 if (!ocsp) {
847 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
848 goto out;
849 }
850 }
851
852 /* According to comments on "chunk_dup", the
853 previous chunk buffer will be freed */
854 if (!chunk_dup(&ocsp->response, ocsp_response)) {
855 memprintf(err, "OCSP response: Memory allocation error");
856 goto out;
857 }
858
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200859 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
860
Emeric Brun4147b2e2014-06-16 18:36:30 +0200861 ret = 0;
862out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100863 ERR_clear_error();
864
Emeric Brun4147b2e2014-06-16 18:36:30 +0200865 if (bs)
866 OCSP_BASICRESP_free(bs);
867
868 if (resp)
869 OCSP_RESPONSE_free(resp);
870
871 return ret;
872}
873/*
874 * External function use to update the OCSP response in the OCSP response's
875 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
876 * to update in DER format.
877 *
878 * Returns 0 on success, 1 in error case.
879 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200880int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200881{
882 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
883}
884
885/*
886 * This function load the OCSP Resonse in DER format contained in file at
887 * path 'ocsp_path' and call 'ssl_sock_load_ocsp_response'
888 *
889 * Returns 0 on success, 1 in error case.
890 */
891static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct certificate_ocsp *ocsp, OCSP_CERTID *cid, char **err)
892{
893 int fd = -1;
894 int r = 0;
895 int ret = 1;
896
897 fd = open(ocsp_path, O_RDONLY);
898 if (fd == -1) {
899 memprintf(err, "Error opening OCSP response file");
900 goto end;
901 }
902
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200903 trash.data = 0;
904 while (trash.data < trash.size) {
905 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200906 if (r < 0) {
907 if (errno == EINTR)
908 continue;
909
910 memprintf(err, "Error reading OCSP response from file");
911 goto end;
912 }
913 else if (r == 0) {
914 break;
915 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200916 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200917 }
918
919 close(fd);
920 fd = -1;
921
922 ret = ssl_sock_load_ocsp_response(&trash, ocsp, cid, err);
923end:
924 if (fd != -1)
925 close(fd);
926
927 return ret;
928}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100929#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200930
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100931#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
932static 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)
933{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100934 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100935 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100936 struct connection *conn;
937 int head;
938 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100939 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100940
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200941 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200942 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100943 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
944
945 keys = ref->tlskeys;
946 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100947
948 if (enc) {
949 memcpy(key_name, keys[head].name, 16);
950
951 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100952 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100953
Emeric Brun9e754772019-01-10 17:51:55 +0100954 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100955
Emeric Brun9e754772019-01-10 17:51:55 +0100956 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
957 goto end;
958
Willy Tarreau9356dac2019-05-10 09:22:53 +0200959 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100960 ret = 1;
961 }
962 else if (ref->key_size_bits == 256 ) {
963
964 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
965 goto end;
966
Willy Tarreau9356dac2019-05-10 09:22:53 +0200967 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100968 ret = 1;
969 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100970 } else {
971 for (i = 0; i < TLS_TICKETS_NO; i++) {
972 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
973 goto found;
974 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100975 ret = 0;
976 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100977
Christopher Faulet16f45c82018-02-16 11:23:49 +0100978 found:
Emeric Brun9e754772019-01-10 17:51:55 +0100979 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200980 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100981 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
982 goto end;
983 /* 2 for key renewal, 1 if current key is still valid */
984 ret = i ? 2 : 1;
985 }
986 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200987 HMAC_Init_ex(hctx, keys[(head + i) % TLS_TICKETS_NO].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100988 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
989 goto end;
990 /* 2 for key renewal, 1 if current key is still valid */
991 ret = i ? 2 : 1;
992 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100993 }
Emeric Brun9e754772019-01-10 17:51:55 +0100994
Christopher Faulet16f45c82018-02-16 11:23:49 +0100995 end:
996 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
997 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200998}
999
1000struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
1001{
1002 struct tls_keys_ref *ref;
1003
1004 list_for_each_entry(ref, &tlskeys_reference, list)
1005 if (ref->filename && strcmp(filename, ref->filename) == 0)
1006 return ref;
1007 return NULL;
1008}
1009
1010struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1011{
1012 struct tls_keys_ref *ref;
1013
1014 list_for_each_entry(ref, &tlskeys_reference, list)
1015 if (ref->unique_id == unique_id)
1016 return ref;
1017 return NULL;
1018}
1019
Emeric Brun9e754772019-01-10 17:51:55 +01001020/* Update the key into ref: if keysize doesnt
1021 * match existing ones, this function returns -1
1022 * else it returns 0 on success.
1023 */
1024int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001025 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001026{
Emeric Brun9e754772019-01-10 17:51:55 +01001027 if (ref->key_size_bits == 128) {
1028 if (tlskey->data != sizeof(struct tls_sess_key_128))
1029 return -1;
1030 }
1031 else if (ref->key_size_bits == 256) {
1032 if (tlskey->data != sizeof(struct tls_sess_key_256))
1033 return -1;
1034 }
1035 else
1036 return -1;
1037
Christopher Faulet16f45c82018-02-16 11:23:49 +01001038 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001039 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1040 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001041 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1042 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001043
1044 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001045}
1046
Willy Tarreau83061a82018-07-13 11:56:34 +02001047int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001048{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001049 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1050
1051 if(!ref) {
1052 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1053 return 1;
1054 }
Emeric Brun9e754772019-01-10 17:51:55 +01001055 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1056 memprintf(err, "Invalid key size");
1057 return 1;
1058 }
1059
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001060 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001061}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001062
1063/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001064 * automatic ids. It's called just after the basic checks. It returns
1065 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001066 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001067static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001068{
1069 int i = 0;
1070 struct tls_keys_ref *ref, *ref2, *ref3;
1071 struct list tkr = LIST_HEAD_INIT(tkr);
1072
1073 list_for_each_entry(ref, &tlskeys_reference, list) {
1074 if (ref->unique_id == -1) {
1075 /* Look for the first free id. */
1076 while (1) {
1077 list_for_each_entry(ref2, &tlskeys_reference, list) {
1078 if (ref2->unique_id == i) {
1079 i++;
1080 break;
1081 }
1082 }
1083 if (&ref2->list == &tlskeys_reference)
1084 break;
1085 }
1086
1087 /* Uses the unique id and increment it for the next entry. */
1088 ref->unique_id = i;
1089 i++;
1090 }
1091 }
1092
1093 /* This sort the reference list by id. */
1094 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1095 LIST_DEL(&ref->list);
1096 list_for_each_entry(ref3, &tkr, list) {
1097 if (ref->unique_id < ref3->unique_id) {
1098 LIST_ADDQ(&ref3->list, &ref->list);
1099 break;
1100 }
1101 }
1102 if (&ref3->list == &tkr)
1103 LIST_ADDQ(&tkr, &ref->list);
1104 }
1105
1106 /* swap root */
1107 LIST_ADD(&tkr, &tlskeys_reference);
1108 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001109 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001110}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001111#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1112
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001113#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001114int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1115{
1116 switch (evp_keytype) {
1117 case EVP_PKEY_RSA:
1118 return 2;
1119 case EVP_PKEY_DSA:
1120 return 0;
1121 case EVP_PKEY_EC:
1122 return 1;
1123 }
1124
1125 return -1;
1126}
1127
Emeric Brun4147b2e2014-06-16 18:36:30 +02001128/*
1129 * Callback used to set OCSP status extension content in server hello.
1130 */
1131int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1132{
yanbzhube2774d2015-12-10 15:07:30 -05001133 struct certificate_ocsp *ocsp;
1134 struct ocsp_cbk_arg *ocsp_arg;
1135 char *ssl_buf;
1136 EVP_PKEY *ssl_pkey;
1137 int key_type;
1138 int index;
1139
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001140 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001141
1142 ssl_pkey = SSL_get_privatekey(ssl);
1143 if (!ssl_pkey)
1144 return SSL_TLSEXT_ERR_NOACK;
1145
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001146 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001147
1148 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1149 ocsp = ocsp_arg->s_ocsp;
1150 else {
1151 /* For multiple certs per context, we have to find the correct OCSP response based on
1152 * the certificate type
1153 */
1154 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1155
1156 if (index < 0)
1157 return SSL_TLSEXT_ERR_NOACK;
1158
1159 ocsp = ocsp_arg->m_ocsp[index];
1160
1161 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001162
1163 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001164 !ocsp->response.area ||
1165 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001166 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001167 return SSL_TLSEXT_ERR_NOACK;
1168
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001169 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001170 if (!ssl_buf)
1171 return SSL_TLSEXT_ERR_NOACK;
1172
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001173 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1174 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001175
1176 return SSL_TLSEXT_ERR_OK;
1177}
1178
1179/*
1180 * This function enables the handling of OCSP status extension on 'ctx' if a
1181 * file name 'cert_path' suffixed using ".ocsp" is present.
1182 * To enable OCSP status extension, the issuer's certificate is mandatory.
1183 * It should be present in the certificate's extra chain builded from file
1184 * 'cert_path'. If not found, the issuer certificate is loaded from a file
1185 * named 'cert_path' suffixed using '.issuer'.
1186 *
1187 * In addition, ".ocsp" file content is loaded as a DER format of an OCSP
1188 * response. If file is empty or content is not a valid OCSP response,
1189 * OCSP status extension is enabled but OCSP response is ignored (a warning
1190 * is displayed).
1191 *
1192 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001193 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001194 */
1195static int ssl_sock_load_ocsp(SSL_CTX *ctx, const char *cert_path)
1196{
1197
1198 BIO *in = NULL;
1199 X509 *x, *xi = NULL, *issuer = NULL;
1200 STACK_OF(X509) *chain = NULL;
1201 OCSP_CERTID *cid = NULL;
1202 SSL *ssl;
1203 char ocsp_path[MAXPATHLEN+1];
1204 int i, ret = -1;
1205 struct stat st;
1206 struct certificate_ocsp *ocsp = NULL, *iocsp;
1207 char *warn = NULL;
1208 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001209 pem_password_cb *passwd_cb;
1210 void *passwd_cb_userdata;
1211 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001212
1213 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1214
1215 if (stat(ocsp_path, &st))
1216 return 1;
1217
1218 ssl = SSL_new(ctx);
1219 if (!ssl)
1220 goto out;
1221
1222 x = SSL_get_certificate(ssl);
1223 if (!x)
1224 goto out;
1225
1226 /* Try to lookup for issuer in certificate extra chain */
1227#ifdef SSL_CTRL_GET_EXTRA_CHAIN_CERTS
1228 SSL_CTX_get_extra_chain_certs(ctx, &chain);
1229#else
1230 chain = ctx->extra_certs;
1231#endif
1232 for (i = 0; i < sk_X509_num(chain); i++) {
1233 issuer = sk_X509_value(chain, i);
1234 if (X509_check_issued(issuer, x) == X509_V_OK)
1235 break;
1236 else
1237 issuer = NULL;
1238 }
1239
1240 /* If not found try to load issuer from a suffixed file */
1241 if (!issuer) {
1242 char issuer_path[MAXPATHLEN+1];
1243
1244 in = BIO_new(BIO_s_file());
1245 if (!in)
1246 goto out;
1247
1248 snprintf(issuer_path, MAXPATHLEN+1, "%s.issuer", cert_path);
1249 if (BIO_read_filename(in, issuer_path) <= 0)
1250 goto out;
1251
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001252 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
1253 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
1254
1255 xi = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001256 if (!xi)
1257 goto out;
1258
1259 if (X509_check_issued(xi, x) != X509_V_OK)
1260 goto out;
1261
1262 issuer = xi;
1263 }
1264
1265 cid = OCSP_cert_to_id(0, x, issuer);
1266 if (!cid)
1267 goto out;
1268
1269 i = i2d_OCSP_CERTID(cid, NULL);
1270 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1271 goto out;
1272
Vincent Bernat02779b62016-04-03 13:48:43 +02001273 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001274 if (!ocsp)
1275 goto out;
1276
1277 p = ocsp->key_data;
1278 i2d_OCSP_CERTID(cid, &p);
1279
1280 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1281 if (iocsp == ocsp)
1282 ocsp = NULL;
1283
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001284#ifndef SSL_CTX_get_tlsext_status_cb
1285# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1286 *cb = (void (*) (void))ctx->tlsext_status_cb;
1287#endif
1288 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1289
1290 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001291 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001292 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001293
1294 cb_arg->is_single = 1;
1295 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001296
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001297 pkey = X509_get_pubkey(x);
1298 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1299 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001300
1301 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1302 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1303 } else {
1304 /*
1305 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1306 * Update that cb_arg with the new cert's staple
1307 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001308 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001309 struct certificate_ocsp *tmp_ocsp;
1310 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001311 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001312 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001313
1314#ifdef SSL_CTX_get_tlsext_status_arg
1315 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1316#else
1317 cb_arg = ctx->tlsext_status_arg;
1318#endif
yanbzhube2774d2015-12-10 15:07:30 -05001319
1320 /*
1321 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1322 * the order of operations below matter, take care when changing it
1323 */
1324 tmp_ocsp = cb_arg->s_ocsp;
1325 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1326 cb_arg->s_ocsp = NULL;
1327 cb_arg->m_ocsp[index] = tmp_ocsp;
1328 cb_arg->is_single = 0;
1329 cb_arg->single_kt = 0;
1330
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001331 pkey = X509_get_pubkey(x);
1332 key_type = EVP_PKEY_base_id(pkey);
1333 EVP_PKEY_free(pkey);
1334
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001335 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001336 if (index >= 0 && !cb_arg->m_ocsp[index])
1337 cb_arg->m_ocsp[index] = iocsp;
1338
1339 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001340
1341 ret = 0;
1342
1343 warn = NULL;
1344 if (ssl_sock_load_ocsp_response_from_file(ocsp_path, iocsp, cid, &warn)) {
1345 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001346 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001347 }
1348
1349out:
1350 if (ssl)
1351 SSL_free(ssl);
1352
1353 if (in)
1354 BIO_free(in);
1355
1356 if (xi)
1357 X509_free(xi);
1358
1359 if (cid)
1360 OCSP_CERTID_free(cid);
1361
1362 if (ocsp)
1363 free(ocsp);
1364
1365 if (warn)
1366 free(warn);
1367
1368
1369 return ret;
1370}
1371
1372#endif
1373
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001374#ifdef OPENSSL_IS_BORINGSSL
1375static int ssl_sock_set_ocsp_response_from_file(SSL_CTX *ctx, const char *cert_path)
1376{
1377 char ocsp_path[MAXPATHLEN+1];
1378 struct stat st;
1379 int fd = -1, r = 0;
1380
1381 snprintf(ocsp_path, MAXPATHLEN+1, "%s.ocsp", cert_path);
1382 if (stat(ocsp_path, &st))
1383 return 0;
1384
1385 fd = open(ocsp_path, O_RDONLY);
1386 if (fd == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001387 ha_warning("Error opening OCSP response file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001388 return -1;
1389 }
1390
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001391 trash.data = 0;
1392 while (trash.data < trash.size) {
1393 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001394 if (r < 0) {
1395 if (errno == EINTR)
1396 continue;
Christopher Faulet767a84b2017-11-24 16:50:31 +01001397 ha_warning("Error reading OCSP response from file %s.\n", ocsp_path);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001398 close(fd);
1399 return -1;
1400 }
1401 else if (r == 0) {
1402 break;
1403 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001404 trash.data += r;
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001405 }
1406 close(fd);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001407 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *) trash.area,
1408 trash.data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001409}
1410#endif
1411
Willy Tarreau5db847a2019-05-09 14:13:35 +02001412#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001413
1414#define CT_EXTENSION_TYPE 18
1415
1416static int sctl_ex_index = -1;
1417
1418/*
1419 * Try to parse Signed Certificate Timestamp List structure. This function
1420 * makes only basic test if the data seems like SCTL. No signature validation
1421 * is performed.
1422 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001423static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001424{
1425 int ret = 1;
1426 int len, pos, sct_len;
1427 unsigned char *data;
1428
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001429 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001430 goto out;
1431
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001432 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001433 len = (data[0] << 8) | data[1];
1434
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001435 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001436 goto out;
1437
1438 data = data + 2;
1439 pos = 0;
1440 while (pos < len) {
1441 if (len - pos < 2)
1442 goto out;
1443
1444 sct_len = (data[pos] << 8) | data[pos + 1];
1445 if (pos + sct_len + 2 > len)
1446 goto out;
1447
1448 pos += sct_len + 2;
1449 }
1450
1451 ret = 0;
1452
1453out:
1454 return ret;
1455}
1456
Willy Tarreau83061a82018-07-13 11:56:34 +02001457static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1458 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001459{
1460 int fd = -1;
1461 int r = 0;
1462 int ret = 1;
1463
1464 *sctl = NULL;
1465
1466 fd = open(sctl_path, O_RDONLY);
1467 if (fd == -1)
1468 goto end;
1469
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001470 trash.data = 0;
1471 while (trash.data < trash.size) {
1472 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001473 if (r < 0) {
1474 if (errno == EINTR)
1475 continue;
1476
1477 goto end;
1478 }
1479 else if (r == 0) {
1480 break;
1481 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001482 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001483 }
1484
1485 ret = ssl_sock_parse_sctl(&trash);
1486 if (ret)
1487 goto end;
1488
Vincent Bernat02779b62016-04-03 13:48:43 +02001489 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001490 if (!chunk_dup(*sctl, &trash)) {
1491 free(*sctl);
1492 *sctl = NULL;
1493 goto end;
1494 }
1495
1496end:
1497 if (fd != -1)
1498 close(fd);
1499
1500 return ret;
1501}
1502
1503int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1504{
Willy Tarreau83061a82018-07-13 11:56:34 +02001505 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001506
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001507 *out = (unsigned char *) sctl->area;
1508 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001509
1510 return 1;
1511}
1512
1513int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1514{
1515 return 1;
1516}
1517
1518static int ssl_sock_load_sctl(SSL_CTX *ctx, const char *cert_path)
1519{
1520 char sctl_path[MAXPATHLEN+1];
1521 int ret = -1;
1522 struct stat st;
Willy Tarreau83061a82018-07-13 11:56:34 +02001523 struct buffer *sctl = NULL;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001524
1525 snprintf(sctl_path, MAXPATHLEN+1, "%s.sctl", cert_path);
1526
1527 if (stat(sctl_path, &st))
1528 return 1;
1529
1530 if (ssl_sock_load_sctl_from_file(sctl_path, &sctl))
1531 goto out;
1532
1533 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL)) {
1534 free(sctl);
1535 goto out;
1536 }
1537
1538 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1539
1540 ret = 0;
1541
1542out:
1543 return ret;
1544}
1545
1546#endif
1547
Emeric Brune1f38db2012-09-03 20:36:47 +02001548void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1549{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001550 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001551 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001552 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001553 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001554
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001555#ifndef SSL_OP_NO_RENEGOTIATION
1556 /* Please note that BoringSSL defines this macro to zero so don't
1557 * change this to #if and do not assign a default value to this macro!
1558 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001559 if (where & SSL_CB_HANDSHAKE_START) {
1560 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001561 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 +02001562 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001563 conn->err_code = CO_ER_SSL_RENEG;
1564 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001565 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001566#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001567
1568 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001569 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001570 /* Long certificate chains optimz
1571 If write and read bios are differents, we
1572 consider that the buffering was activated,
1573 so we rise the output buffer size from 4k
1574 to 16k */
1575 write_bio = SSL_get_wbio(ssl);
1576 if (write_bio != SSL_get_rbio(ssl)) {
1577 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001578 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001579 }
1580 }
1581 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001582}
1583
Emeric Brune64aef12012-09-21 13:15:06 +02001584/* Callback is called for each certificate of the chain during a verify
1585 ok is set to 1 if preverify detect no error on current certificate.
1586 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001587int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001588{
1589 SSL *ssl;
1590 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001591 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001592 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001593
1594 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001595 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001596
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001597 ctx = conn->xprt_ctx;
1598
1599 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001600
Emeric Brun81c00f02012-09-21 14:31:21 +02001601 if (ok) /* no errors */
1602 return ok;
1603
1604 depth = X509_STORE_CTX_get_error_depth(x_store);
1605 err = X509_STORE_CTX_get_error(x_store);
1606
1607 /* check if CA error needs to be ignored */
1608 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001609 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1610 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1611 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001612 }
1613
Willy Tarreau07d94e42018-09-20 10:57:52 +02001614 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001615 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001616 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001617 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001618 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001619
Willy Tarreau20879a02012-12-03 16:32:10 +01001620 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001621 return 0;
1622 }
1623
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001624 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1625 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001626
Emeric Brun81c00f02012-09-21 14:31:21 +02001627 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001628 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001629 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001630 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001631 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001632 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001633
Willy Tarreau20879a02012-12-03 16:32:10 +01001634 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001635 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001636}
1637
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001638static inline
1639void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001640 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001641{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001642 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001643 unsigned char *msg;
1644 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001645 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001646
1647 /* This function is called for "from client" and "to server"
1648 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001649 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001650 */
1651
1652 /* "write_p" is set to 0 is the bytes are received messages,
1653 * otherwise it is set to 1.
1654 */
1655 if (write_p != 0)
1656 return;
1657
1658 /* content_type contains the type of message received or sent
1659 * according with the SSL/TLS protocol spec. This message is
1660 * encoded with one byte. The value 256 (two bytes) is used
1661 * for designing the SSL/TLS record layer. According with the
1662 * rfc6101, the expected message (other than 256) are:
1663 * - change_cipher_spec(20)
1664 * - alert(21)
1665 * - handshake(22)
1666 * - application_data(23)
1667 * - (255)
1668 * We are interessed by the handshake and specially the client
1669 * hello.
1670 */
1671 if (content_type != 22)
1672 return;
1673
1674 /* The message length is at least 4 bytes, containing the
1675 * message type and the message length.
1676 */
1677 if (len < 4)
1678 return;
1679
1680 /* First byte of the handshake message id the type of
1681 * message. The konwn types are:
1682 * - hello_request(0)
1683 * - client_hello(1)
1684 * - server_hello(2)
1685 * - certificate(11)
1686 * - server_key_exchange (12)
1687 * - certificate_request(13)
1688 * - server_hello_done(14)
1689 * We are interested by the client hello.
1690 */
1691 msg = (unsigned char *)buf;
1692 if (msg[0] != 1)
1693 return;
1694
1695 /* Next three bytes are the length of the message. The total length
1696 * must be this decoded length + 4. If the length given as argument
1697 * is not the same, we abort the protocol dissector.
1698 */
1699 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1700 if (len < rec_len + 4)
1701 return;
1702 msg += 4;
1703 end = msg + rec_len;
1704 if (end < msg)
1705 return;
1706
1707 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1708 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001709 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1710 */
1711 msg += 1 + 1 + 4 + 28;
1712 if (msg > end)
1713 return;
1714
1715 /* Next, is session id:
1716 * if present, we have to jump by length + 1 for the size information
1717 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001718 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001719 if (msg[0] > 0)
1720 msg += msg[0];
1721 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001722 if (msg > end)
1723 return;
1724
1725 /* Next two bytes are the ciphersuite length. */
1726 if (msg + 2 > end)
1727 return;
1728 rec_len = (msg[0] << 8) + msg[1];
1729 msg += 2;
1730 if (msg + rec_len > end || msg + rec_len < msg)
1731 return;
1732
Willy Tarreaubafbe012017-11-24 17:34:44 +01001733 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001734 if (!capture)
1735 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001736 /* Compute the xxh64 of the ciphersuite. */
1737 capture->xxh64 = XXH64(msg, rec_len, 0);
1738
1739 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001740 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1741 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001742 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001743
1744 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001745}
1746
Emeric Brun29f037d2014-04-25 19:05:36 +02001747/* Callback is called for ssl protocol analyse */
1748void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1749{
Emeric Brun29f037d2014-04-25 19:05:36 +02001750#ifdef TLS1_RT_HEARTBEAT
1751 /* test heartbeat received (write_p is set to 0
1752 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001753 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001754 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001755 struct ssl_sock_ctx *ctx = conn->ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001756 const unsigned char *p = buf;
1757 unsigned int payload;
1758
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001759 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001760
1761 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1762 if (*p != TLS1_HB_REQUEST)
1763 return;
1764
Willy Tarreauaeed6722014-04-25 23:59:58 +02001765 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001766 goto kill_it;
1767
1768 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001769 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001770 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001771 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001772 /* We have a clear heartbleed attack (CVE-2014-0160), the
1773 * advertised payload is larger than the advertised packet
1774 * length, so we have garbage in the buffer between the
1775 * payload and the end of the buffer (p+len). We can't know
1776 * if the SSL stack is patched, and we don't know if we can
1777 * safely wipe out the area between p+3+len and payload.
1778 * So instead, we prevent the response from being sent by
1779 * setting the max_send_fragment to 0 and we report an SSL
1780 * error, which will kill this connection. It will be reported
1781 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001782 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1783 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001784 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001785 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1786 return;
1787 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001788#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001789 if (global_ssl.capture_cipherlist > 0)
1790 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001791}
1792
Bernard Spil13c53f82018-02-15 13:34:58 +01001793#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001794static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1795 const unsigned char *in, unsigned int inlen,
1796 void *arg)
1797{
1798 struct server *srv = arg;
1799
1800 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1801 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1802 return SSL_TLSEXT_ERR_OK;
1803 return SSL_TLSEXT_ERR_NOACK;
1804}
1805#endif
1806
1807#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001808/* This callback is used so that the server advertises the list of
1809 * negociable protocols for NPN.
1810 */
1811static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1812 unsigned int *len, void *arg)
1813{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001814 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001815
1816 *data = (const unsigned char *)conf->npn_str;
1817 *len = conf->npn_len;
1818 return SSL_TLSEXT_ERR_OK;
1819}
1820#endif
1821
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001822#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001823/* This callback is used so that the server advertises the list of
1824 * negociable protocols for ALPN.
1825 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001826static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1827 unsigned char *outlen,
1828 const unsigned char *server,
1829 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001830{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001831 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001832
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001833 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1834 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1835 return SSL_TLSEXT_ERR_NOACK;
1836 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001837 return SSL_TLSEXT_ERR_OK;
1838}
1839#endif
1840
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001841#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001842#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001843
Christopher Faulet30548802015-06-11 13:39:32 +02001844/* Create a X509 certificate with the specified servername and serial. This
1845 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001846static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001847ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001848{
Christopher Faulet7969a332015-10-09 11:15:03 +02001849 X509 *cacert = bind_conf->ca_sign_cert;
1850 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001851 SSL_CTX *ssl_ctx = NULL;
1852 X509 *newcrt = NULL;
1853 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001854 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001855 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001856 X509_NAME *name;
1857 const EVP_MD *digest;
1858 X509V3_CTX ctx;
1859 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001860 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001861
Christopher Faulet48a83322017-07-28 16:56:09 +02001862 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001863#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001864 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1865#else
1866 tmp_ssl = SSL_new(bind_conf->default_ctx);
1867 if (tmp_ssl)
1868 pkey = SSL_get_privatekey(tmp_ssl);
1869#endif
1870 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001871 goto mkcert_error;
1872
1873 /* Create the certificate */
1874 if (!(newcrt = X509_new()))
1875 goto mkcert_error;
1876
1877 /* Set version number for the certificate (X509v3) and the serial
1878 * number */
1879 if (X509_set_version(newcrt, 2L) != 1)
1880 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001881 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001882
1883 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001884 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1885 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001886 goto mkcert_error;
1887
1888 /* set public key in the certificate */
1889 if (X509_set_pubkey(newcrt, pkey) != 1)
1890 goto mkcert_error;
1891
1892 /* Set issuer name from the CA */
1893 if (!(name = X509_get_subject_name(cacert)))
1894 goto mkcert_error;
1895 if (X509_set_issuer_name(newcrt, name) != 1)
1896 goto mkcert_error;
1897
1898 /* Set the subject name using the same, but the CN */
1899 name = X509_NAME_dup(name);
1900 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1901 (const unsigned char *)servername,
1902 -1, -1, 0) != 1) {
1903 X509_NAME_free(name);
1904 goto mkcert_error;
1905 }
1906 if (X509_set_subject_name(newcrt, name) != 1) {
1907 X509_NAME_free(name);
1908 goto mkcert_error;
1909 }
1910 X509_NAME_free(name);
1911
1912 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001913 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001914 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1915 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1916 X509_EXTENSION *ext;
1917
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001918 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001919 goto mkcert_error;
1920 if (!X509_add_ext(newcrt, ext, -1)) {
1921 X509_EXTENSION_free(ext);
1922 goto mkcert_error;
1923 }
1924 X509_EXTENSION_free(ext);
1925 }
1926
1927 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001928
1929 key_type = EVP_PKEY_base_id(capkey);
1930
1931 if (key_type == EVP_PKEY_DSA)
1932 digest = EVP_sha1();
1933 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001934 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001935 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001936 digest = EVP_sha256();
1937 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001938#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001939 int nid;
1940
1941 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1942 goto mkcert_error;
1943 if (!(digest = EVP_get_digestbynid(nid)))
1944 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001945#else
1946 goto mkcert_error;
1947#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001948 }
1949
Christopher Faulet31af49d2015-06-09 17:29:50 +02001950 if (!(X509_sign(newcrt, capkey, digest)))
1951 goto mkcert_error;
1952
1953 /* Create and set the new SSL_CTX */
1954 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1955 goto mkcert_error;
1956 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1957 goto mkcert_error;
1958 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1959 goto mkcert_error;
1960 if (!SSL_CTX_check_private_key(ssl_ctx))
1961 goto mkcert_error;
1962
1963 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001964
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001965#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001966 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001967#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001968#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1969 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001970 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001971 EC_KEY *ecc;
1972 int nid;
1973
1974 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1975 goto end;
1976 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1977 goto end;
1978 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1979 EC_KEY_free(ecc);
1980 }
1981#endif
1982 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983 return ssl_ctx;
1984
1985 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001986 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001987 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001988 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1989 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001990 return NULL;
1991}
1992
Christopher Faulet7969a332015-10-09 11:15:03 +02001993SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001994ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001995{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001996 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001997 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001998
Olivier Houchard66ab4982019-02-26 18:37:15 +01001999 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02002000}
2001
Christopher Faulet30548802015-06-11 13:39:32 +02002002/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02002003 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02002004SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02002005ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02002006{
2007 struct lru64 *lru = NULL;
2008
2009 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002010 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002011 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002012 if (lru && lru->domain) {
2013 if (ssl)
2014 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002015 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002016 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002017 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02002018 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02002019 }
2020 return NULL;
2021}
2022
Emeric Brun821bb9b2017-06-15 16:37:39 +02002023/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
2024 * function is not thread-safe, it should only be used to check if a certificate
2025 * exists in the lru cache (with no warranty it will not be removed by another
2026 * thread). It is kept for backward compatibility. */
2027SSL_CTX *
2028ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
2029{
2030 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
2031}
2032
Christopher Fauletd2cab922015-07-28 16:03:47 +02002033/* Set a certificate int the LRU cache used to store generated
2034 * certificate. Return 0 on success, otherwise -1 */
2035int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002036ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02002037{
2038 struct lru64 *lru = NULL;
2039
2040 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002041 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002042 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02002043 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002044 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002045 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02002046 }
Christopher Faulet30548802015-06-11 13:39:32 +02002047 if (lru->domain && lru->data)
2048 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02002049 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002050 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002051 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02002052 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02002053 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02002054}
2055
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002056/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02002057unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002058ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02002059{
2060 return XXH32(data, len, ssl_ctx_lru_seed);
2061}
2062
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002063/* Generate a cert and immediately assign it to the SSL session so that the cert's
2064 * refcount is maintained regardless of the cert's presence in the LRU cache.
2065 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002066static int
Christopher Faulet7969a332015-10-09 11:15:03 +02002067ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02002068{
2069 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002070 SSL_CTX *ssl_ctx = NULL;
2071 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002072 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002073
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002074 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02002075 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002076 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002077 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002078 if (lru && lru->domain)
2079 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02002080 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002081 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002082 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02002083 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002084 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002085 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002086 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002087 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002088 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01002089 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002090 SSL_set_SSL_CTX(ssl, ssl_ctx);
2091 /* No LRU cache, this CTX will be released as soon as the session dies */
2092 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002093 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02002094 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002095 return 0;
2096}
2097static int
2098ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
2099{
2100 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002101 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002102
2103 conn_get_to_addr(conn);
2104 if (conn->flags & CO_FL_ADDR_TO_SET) {
2105 key = ssl_sock_generated_cert_key(&conn->addr.to, get_addr_len(&conn->addr.to));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002106 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002107 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002108 }
2109 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002110}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002111#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002112
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002113#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002114typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2115
2116static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002117{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002118#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002119 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002120 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2121#endif
2122}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002123static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2124 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002125 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2126}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002127static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002128#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002129 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002130 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2131#endif
2132}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002133static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002134#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002135 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002136 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2137#endif
2138}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002139/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002140static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2141/* Unusable in this context. */
2142static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2143static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2144static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2145static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2146static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002147#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002148typedef enum { SET_MIN, SET_MAX } set_context_func;
2149
2150static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2151 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002152 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2153}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002154static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2155 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2156 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2157}
2158static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2159 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002160 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2161}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002162static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2163 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2164 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2165}
2166static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2167 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002168 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2169}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002170static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2171 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2172 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2173}
2174static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2175 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002176 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2177}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002178static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2179 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2180 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2181}
2182static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002183#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002184 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002185 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2186#endif
2187}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002188static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2189#if SSL_OP_NO_TLSv1_3
2190 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2191 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002192#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002193}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002194#endif
2195static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2196static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002197
2198static struct {
2199 int option;
2200 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002201 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2202 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002203 const char *name;
2204} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002205 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2206 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2207 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2208 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2209 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2210 {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 +02002211};
2212
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002213static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2214{
2215 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2216 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2217 SSL_set_SSL_CTX(ssl, ctx);
2218}
2219
Willy Tarreau5db847a2019-05-09 14:13:35 +02002220#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221
2222static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2223{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002224 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002225 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002226
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002227 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2228 return SSL_TLSEXT_ERR_OK;
2229 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002230}
2231
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002232#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002233static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2234{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002235 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002236#else
2237static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2238{
2239#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002240 struct connection *conn;
2241 struct bind_conf *s;
2242 const uint8_t *extension_data;
2243 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002244 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002245
2246 char *wildp = NULL;
2247 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002248 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002249 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002250 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002251 int i;
2252
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002253 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002254 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002255
Olivier Houchard9679ac92017-10-27 14:58:08 +02002256 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002257 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002258#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002259 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2260 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002261#else
2262 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2263#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002264 /*
2265 * The server_name extension was given too much extensibility when it
2266 * was written, so parsing the normal case is a bit complex.
2267 */
2268 size_t len;
2269 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002270 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002271 /* Extract the length of the supplied list of names. */
2272 len = (*extension_data++) << 8;
2273 len |= *extension_data++;
2274 if (len + 2 != extension_len)
2275 goto abort;
2276 /*
2277 * The list in practice only has a single element, so we only consider
2278 * the first one.
2279 */
2280 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2281 goto abort;
2282 extension_len = len - 1;
2283 /* Now we can finally pull out the byte array with the actual hostname. */
2284 if (extension_len <= 2)
2285 goto abort;
2286 len = (*extension_data++) << 8;
2287 len |= *extension_data++;
2288 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2289 || memchr(extension_data, 0, len) != NULL)
2290 goto abort;
2291 servername = extension_data;
2292 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002293 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002294#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2295 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002296 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002297 }
2298#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002299 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002300 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002301 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002302 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002303 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 goto abort;
2305 }
2306
2307 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002308#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002309 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002310#else
2311 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2312#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002313 uint8_t sign;
2314 size_t len;
2315 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002316 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002317 len = (*extension_data++) << 8;
2318 len |= *extension_data++;
2319 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002320 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002321 if (len % 2 != 0)
2322 goto abort;
2323 for (; len > 0; len -= 2) {
2324 extension_data++; /* hash */
2325 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002326 switch (sign) {
2327 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002328 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002329 break;
2330 case TLSEXT_signature_ecdsa:
2331 has_ecdsa_sig = 1;
2332 break;
2333 default:
2334 continue;
2335 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002336 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002337 break;
2338 }
2339 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002340 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002341 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002342 }
2343 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002344 const SSL_CIPHER *cipher;
2345 size_t len;
2346 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002347 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002348#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002349 len = ctx->cipher_suites_len;
2350 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002351#else
2352 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2353#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002354 if (len % 2 != 0)
2355 goto abort;
2356 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002357#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002358 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002359 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002360#else
2361 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2362#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002363 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002364 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002365 break;
2366 }
2367 }
2368 }
2369
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002370 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002371 trash.area[i] = tolower(servername[i]);
2372 if (!wildp && (trash.area[i] == '.'))
2373 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002374 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002375 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002376
2377 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002378 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002379
2380 /* lookup a not neg filter */
2381 for (n = node; n; n = ebmb_next_dup(n)) {
2382 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002383 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002384 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002385 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002386 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002387 break;
2388 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002389 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002390 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002391 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002392 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002393 if (!node_anonymous)
2394 node_anonymous = n;
2395 break;
2396 }
2397 }
2398 }
2399 if (wildp) {
2400 /* lookup in wildcards names */
2401 node = ebst_lookup(&s->sni_w_ctx, wildp);
2402 for (n = node; n; n = ebmb_next_dup(n)) {
2403 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002404 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002405 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002406 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002407 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002408 break;
2409 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002410 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002411 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002412 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002413 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002414 if (!node_anonymous)
2415 node_anonymous = n;
2416 break;
2417 }
2418 }
2419 }
2420 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002421 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002422 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2423 : ((has_rsa_sig && node_rsa) ? node_rsa
2424 : (node_anonymous ? node_anonymous
2425 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2426 : node_rsa /* no rsa signature case (far far away) */
2427 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002428 if (node) {
2429 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002430 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002431 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002432 if (conf) {
2433 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2434 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2435 if (conf->early_data)
2436 allow_early = 1;
2437 }
2438 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002439 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002440#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002441 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002442 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002443 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002444 }
2445#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002446 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002447 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002448 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002449 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002450allow_early:
2451#ifdef OPENSSL_IS_BORINGSSL
2452 if (allow_early)
2453 SSL_set_early_data_enabled(ssl, 1);
2454#else
2455 if (!allow_early)
2456 SSL_set_max_early_data(ssl, 0);
2457#endif
2458 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002459 abort:
2460 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2461 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002462#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002463 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002464#else
2465 *al = SSL_AD_UNRECOGNIZED_NAME;
2466 return 0;
2467#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002468}
2469
2470#else /* OPENSSL_IS_BORINGSSL */
2471
Emeric Brunfc0421f2012-09-07 17:30:07 +02002472/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2473 * warning when no match is found, which implies the default (first) cert
2474 * will keep being used.
2475 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002476static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002477{
2478 const char *servername;
2479 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002480 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002481 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002482 int i;
2483 (void)al; /* shut gcc stupid warning */
2484
2485 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002486 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002487#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002488 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2489 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002490#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002491 if (s->strict_sni)
2492 return SSL_TLSEXT_ERR_ALERT_FATAL;
2493 ssl_sock_switchctx_set(ssl, s->default_ctx);
2494 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002495 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002496
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002497 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002498 if (!servername[i])
2499 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002500 trash.area[i] = tolower(servername[i]);
2501 if (!wildp && (trash.area[i] == '.'))
2502 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002503 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002504 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002505
2506 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002507 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002508
2509 /* lookup a not neg filter */
2510 for (n = node; n; n = ebmb_next_dup(n)) {
2511 if (!container_of(n, struct sni_ctx, name)->neg) {
2512 node = n;
2513 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002514 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002515 }
2516 if (!node && wildp) {
2517 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002518 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002519 }
2520 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002521#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002522 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2523 /* switch ctx done in ssl_sock_generate_certificate */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002524 return SSL_TLSEXT_ERR_OK;
2525 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002526#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002527 if (s->strict_sni)
2528 return SSL_TLSEXT_ERR_ALERT_FATAL;
2529 ssl_sock_switchctx_set(ssl, s->default_ctx);
2530 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002531 }
2532
2533 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002534 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002535 return SSL_TLSEXT_ERR_OK;
2536}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002537#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002538#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2539
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002540#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002541
2542static DH * ssl_get_dh_1024(void)
2543{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002544 static unsigned char dh1024_p[]={
2545 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2546 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2547 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2548 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2549 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2550 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2551 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2552 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2553 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2554 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2555 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2556 };
2557 static unsigned char dh1024_g[]={
2558 0x02,
2559 };
2560
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002561 BIGNUM *p;
2562 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002563 DH *dh = DH_new();
2564 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002565 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2566 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002567
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002568 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002569 DH_free(dh);
2570 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002571 } else {
2572 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002573 }
2574 }
2575 return dh;
2576}
2577
2578static DH *ssl_get_dh_2048(void)
2579{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002580 static unsigned char dh2048_p[]={
2581 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2582 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2583 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2584 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2585 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2586 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2587 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2588 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2589 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2590 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2591 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2592 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2593 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2594 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2595 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2596 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2597 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2598 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2599 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2600 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2601 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2602 0xB7,0x1F,0x77,0xF3,
2603 };
2604 static unsigned char dh2048_g[]={
2605 0x02,
2606 };
2607
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002608 BIGNUM *p;
2609 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002610 DH *dh = DH_new();
2611 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002612 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2613 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002614
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002615 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002616 DH_free(dh);
2617 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002618 } else {
2619 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002620 }
2621 }
2622 return dh;
2623}
2624
2625static DH *ssl_get_dh_4096(void)
2626{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002627 static unsigned char dh4096_p[]={
2628 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2629 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2630 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2631 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2632 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2633 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2634 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2635 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2636 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2637 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2638 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2639 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2640 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2641 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2642 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2643 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2644 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2645 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2646 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2647 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2648 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2649 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2650 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2651 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2652 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2653 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2654 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2655 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2656 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2657 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2658 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2659 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2660 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2661 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2662 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2663 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2664 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2665 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2666 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2667 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2668 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2669 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2670 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002671 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002672 static unsigned char dh4096_g[]={
2673 0x02,
2674 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002675
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002676 BIGNUM *p;
2677 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002678 DH *dh = DH_new();
2679 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002680 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2681 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002682
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002683 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002684 DH_free(dh);
2685 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002686 } else {
2687 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002688 }
2689 }
2690 return dh;
2691}
2692
2693/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002694 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002695static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2696{
2697 DH *dh = NULL;
2698 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002699 int type;
2700
2701 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002702
2703 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2704 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2705 */
2706 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2707 keylen = EVP_PKEY_bits(pkey);
2708 }
2709
Willy Tarreauef934602016-12-22 23:12:01 +01002710 if (keylen > global_ssl.default_dh_param) {
2711 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002712 }
2713
Remi Gacogned3a341a2015-05-29 16:26:17 +02002714 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002715 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002716 }
2717 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002718 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002719 }
2720 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002721 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002722 }
2723
2724 return dh;
2725}
2726
Remi Gacogne47783ef2015-05-29 15:53:22 +02002727static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002728{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002729 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002730 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002731
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002732 if (in == NULL)
2733 goto end;
2734
Remi Gacogne47783ef2015-05-29 15:53:22 +02002735 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002736 goto end;
2737
Remi Gacogne47783ef2015-05-29 15:53:22 +02002738 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2739
2740end:
2741 if (in)
2742 BIO_free(in);
2743
Emeric Brune1b4ed42018-08-16 15:14:12 +02002744 ERR_clear_error();
2745
Remi Gacogne47783ef2015-05-29 15:53:22 +02002746 return dh;
2747}
2748
2749int ssl_sock_load_global_dh_param_from_file(const char *filename)
2750{
2751 global_dh = ssl_sock_get_dh_from_file(filename);
2752
2753 if (global_dh) {
2754 return 0;
2755 }
2756
2757 return -1;
2758}
2759
2760/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
Joseph Herlant017b3da2018-11-15 09:07:59 -08002761 if an error occurred, and 0 if parameter not found. */
Remi Gacogne47783ef2015-05-29 15:53:22 +02002762int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
2763{
2764 int ret = -1;
2765 DH *dh = ssl_sock_get_dh_from_file(file);
2766
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002767 if (dh) {
2768 ret = 1;
2769 SSL_CTX_set_tmp_dh(ctx, dh);
Remi Gacogne4f902b82015-05-28 16:23:00 +02002770
2771 if (ssl_dh_ptr_index >= 0) {
2772 /* store a pointer to the DH params to avoid complaining about
2773 ssl-default-dh-param not being set for this SSL_CTX */
2774 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2775 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002776 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02002777 else if (global_dh) {
2778 SSL_CTX_set_tmp_dh(ctx, global_dh);
2779 ret = 0; /* DH params not found */
2780 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002781 else {
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002782 /* Clear openssl global errors stack */
2783 ERR_clear_error();
2784
Willy Tarreauef934602016-12-22 23:12:01 +01002785 if (global_ssl.default_dh_param <= 1024) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002786 /* we are limited to DH parameter of 1024 bits anyway */
Remi Gacognec7e12632016-07-02 16:26:10 +02002787 if (local_dh_1024 == NULL)
2788 local_dh_1024 = ssl_get_dh_1024();
2789
Remi Gacogne8de54152014-07-15 11:36:40 +02002790 if (local_dh_1024 == NULL)
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002791 goto end;
Willy Tarreau6e774b42014-04-25 21:35:23 +02002792
Remi Gacogne8de54152014-07-15 11:36:40 +02002793 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002794 }
2795 else {
2796 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2797 }
Willy Tarreau6e774b42014-04-25 21:35:23 +02002798
Emeric Brun41fdb3c2013-04-26 11:05:44 +02002799 ret = 0; /* DH params not found */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002800 }
Emeric Brun644cde02012-12-14 11:21:13 +01002801
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002802end:
2803 if (dh)
2804 DH_free(dh);
2805
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002806 return ret;
2807}
2808#endif
2809
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002810static 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 +02002811 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002812{
2813 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002814 int wild = 0, neg = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002815 struct ebmb_node *node;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002816
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002817 if (*name == '!') {
2818 neg = 1;
2819 name++;
2820 }
2821 if (*name == '*') {
2822 wild = 1;
2823 name++;
2824 }
2825 /* !* filter is a nop */
2826 if (neg && wild)
2827 return order;
2828 if (*name) {
2829 int j, len;
2830 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002831 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002832 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002833 if (j >= trash.size)
2834 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002835 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002836
2837 /* Check for duplicates. */
2838 if (wild)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002839 node = ebst_lookup(&s->sni_w_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002840 else
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002841 node = ebst_lookup(&s->sni_ctx, trash.area);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002842 for (; node; node = ebmb_next_dup(node)) {
2843 sc = ebmb_entry(node, struct sni_ctx, name);
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002844 if (sc->ctx == ctx && sc->conf == conf && sc->neg == neg)
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002845 return order;
2846 }
2847
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002848 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002849 if (!sc)
2850 return order;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002851 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002852 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002853 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002854 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002855 sc->order = order++;
2856 sc->neg = neg;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002857 if (kinfo.sig != TLSEXT_signature_anonymous)
2858 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002859 if (wild)
2860 ebst_insert(&s->sni_w_ctx, &sc->name);
2861 else
2862 ebst_insert(&s->sni_ctx, &sc->name);
2863 }
2864 return order;
2865}
2866
yanbzhu488a4d22015-12-01 15:16:07 -05002867
2868/* The following code is used for loading multiple crt files into
2869 * SSL_CTX's based on CN/SAN
2870 */
Willy Tarreau5db847a2019-05-09 14:13:35 +02002871#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002872/* This is used to preload the certifcate, private key
2873 * and Cert Chain of a file passed in via the crt
2874 * argument
2875 *
2876 * This way, we do not have to read the file multiple times
2877 */
2878struct cert_key_and_chain {
2879 X509 *cert;
2880 EVP_PKEY *key;
2881 unsigned int num_chain_certs;
2882 /* This is an array of X509 pointers */
2883 X509 **chain_certs;
2884};
2885
yanbzhu08ce6ab2015-12-02 13:01:29 -05002886#define SSL_SOCK_POSSIBLE_KT_COMBOS (1<<(SSL_SOCK_NUM_KEYTYPES))
2887
2888struct key_combo_ctx {
2889 SSL_CTX *ctx;
2890 int order;
2891};
2892
2893/* Map used for processing multiple keypairs for a single purpose
2894 *
2895 * This maps CN/SNI name to certificate type
2896 */
2897struct sni_keytype {
2898 int keytypes; /* BITMASK for keytypes */
2899 struct ebmb_node name; /* node holding the servername value */
2900};
2901
2902
yanbzhu488a4d22015-12-01 15:16:07 -05002903/* Frees the contents of a cert_key_and_chain
2904 */
2905static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2906{
2907 int i;
2908
2909 if (!ckch)
2910 return;
2911
2912 /* Free the certificate and set pointer to NULL */
2913 if (ckch->cert)
2914 X509_free(ckch->cert);
2915 ckch->cert = NULL;
2916
2917 /* Free the key and set pointer to NULL */
2918 if (ckch->key)
2919 EVP_PKEY_free(ckch->key);
2920 ckch->key = NULL;
2921
2922 /* Free each certificate in the chain */
2923 for (i = 0; i < ckch->num_chain_certs; i++) {
2924 if (ckch->chain_certs[i])
2925 X509_free(ckch->chain_certs[i]);
2926 }
2927
2928 /* Free the chain obj itself and set to NULL */
2929 if (ckch->num_chain_certs > 0) {
2930 free(ckch->chain_certs);
2931 ckch->num_chain_certs = 0;
2932 ckch->chain_certs = NULL;
2933 }
2934
2935}
2936
2937/* checks if a key and cert exists in the ckch
2938 */
2939static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2940{
2941 return (ckch->cert != NULL && ckch->key != NULL);
2942}
2943
2944
2945/* Loads the contents of a crt file (path) into a cert_key_and_chain
2946 * This allows us to carry the contents of the file without having to
2947 * read the file multiple times.
2948 *
2949 * returns:
2950 * 0 on Success
2951 * 1 on SSL Failure
2952 * 2 on file not found
2953 */
2954static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_and_chain *ckch, char **err)
2955{
2956
2957 BIO *in;
2958 X509 *ca = NULL;
2959 int ret = 1;
2960
2961 ssl_sock_free_cert_key_and_chain_contents(ckch);
2962
2963 in = BIO_new(BIO_s_file());
2964 if (in == NULL)
2965 goto end;
2966
2967 if (BIO_read_filename(in, path) <= 0)
2968 goto end;
2969
yanbzhu488a4d22015-12-01 15:16:07 -05002970 /* Read Private Key */
2971 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2972 if (ckch->key == NULL) {
2973 memprintf(err, "%sunable to load private key from file '%s'.\n",
2974 err && *err ? *err : "", path);
2975 goto end;
2976 }
2977
Willy Tarreaubb137a82016-04-06 19:02:38 +02002978 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002979 if (BIO_reset(in) == -1) {
2980 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2981 err && *err ? *err : "", path);
2982 goto end;
2983 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002984
2985 /* Read Certificate */
2986 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2987 if (ckch->cert == NULL) {
2988 memprintf(err, "%sunable to load certificate from file '%s'.\n",
2989 err && *err ? *err : "", path);
2990 goto end;
2991 }
2992
yanbzhu488a4d22015-12-01 15:16:07 -05002993 /* Read Certificate Chain */
2994 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
2995 /* Grow the chain certs */
2996 ckch->num_chain_certs++;
2997 ckch->chain_certs = realloc(ckch->chain_certs, (ckch->num_chain_certs * sizeof(X509 *)));
2998
2999 /* use - 1 here since we just incremented it above */
3000 ckch->chain_certs[ckch->num_chain_certs - 1] = ca;
3001 }
3002 ret = ERR_get_error();
3003 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
3004 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
3005 err && *err ? *err : "", path);
3006 ret = 1;
3007 goto end;
3008 }
3009
3010 ret = 0;
3011
3012end:
3013
3014 ERR_clear_error();
3015 if (in)
3016 BIO_free(in);
3017
3018 /* Something went wrong in one of the reads */
3019 if (ret != 0)
3020 ssl_sock_free_cert_key_and_chain_contents(ckch);
3021
3022 return ret;
3023}
3024
3025/* Loads the info in ckch into ctx
3026 * Currently, this does not process any information about ocsp, dhparams or
3027 * sctl
3028 * Returns
3029 * 0 on success
3030 * 1 on failure
3031 */
3032static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3033{
3034 int i = 0;
3035
3036 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3037 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3038 err && *err ? *err : "", path);
3039 return 1;
3040 }
3041
3042 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3043 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3044 err && *err ? *err : "", path);
3045 return 1;
3046 }
3047
yanbzhu488a4d22015-12-01 15:16:07 -05003048 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
3049 for (i = 0; i < ckch->num_chain_certs; i++) {
3050 if (!SSL_CTX_add1_chain_cert(ctx, ckch->chain_certs[i])) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003051 memprintf(err, "%sunable to load chain certificate #%d into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3052 err && *err ? *err : "", (i+1), path);
yanbzhu488a4d22015-12-01 15:16:07 -05003053 return 1;
3054 }
3055 }
3056
3057 if (SSL_CTX_check_private_key(ctx) <= 0) {
3058 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3059 err && *err ? *err : "", path);
3060 return 1;
3061 }
3062
3063 return 0;
3064}
3065
yanbzhu08ce6ab2015-12-02 13:01:29 -05003066
3067static void ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
3068{
3069 struct sni_keytype *s_kt = NULL;
3070 struct ebmb_node *node;
3071 int i;
3072
3073 for (i = 0; i < trash.size; i++) {
3074 if (!str[i])
3075 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003076 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003077 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003078 trash.area[i] = 0;
3079 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003080 if (!node) {
3081 /* CN not found in tree */
3082 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3083 /* Using memcpy here instead of strncpy.
3084 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3085 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3086 */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003087 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003088 s_kt->keytypes = 0;
3089 ebst_insert(sni_keytypes, &s_kt->name);
3090 } else {
3091 /* CN found in tree */
3092 s_kt = container_of(node, struct sni_keytype, name);
3093 }
3094
3095 /* Mark that this CN has the keytype of key_index via keytypes mask */
3096 s_kt->keytypes |= 1<<key_index;
3097
3098}
3099
3100
3101/* Given a path that does not exist, try to check for path.rsa, path.dsa and path.ecdsa files.
3102 * If any are found, group these files into a set of SSL_CTX*
3103 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3104 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003105 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003106 *
3107 * Returns
3108 * 0 on success
3109 * 1 on failure
3110 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003111static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3112 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003113{
3114 char fp[MAXPATHLEN+1] = {0};
3115 int n = 0;
3116 int i = 0;
3117 struct cert_key_and_chain certs_and_keys[SSL_SOCK_NUM_KEYTYPES] = { {0} };
3118 struct eb_root sni_keytypes_map = { {0} };
3119 struct ebmb_node *node;
3120 struct ebmb_node *next;
3121 /* Array of SSL_CTX pointers corresponding to each possible combo
3122 * of keytypes
3123 */
3124 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3125 int rv = 0;
3126 X509_NAME *xname = NULL;
3127 char *str = NULL;
3128#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3129 STACK_OF(GENERAL_NAME) *names = NULL;
3130#endif
3131
3132 /* Load all possible certs and keys */
3133 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3134 struct stat buf;
3135
3136 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3137 if (stat(fp, &buf) == 0) {
3138 if (ssl_sock_load_crt_file_into_ckch(fp, &certs_and_keys[n], err) == 1) {
3139 rv = 1;
3140 goto end;
3141 }
3142 }
3143 }
3144
3145 /* Process each ckch and update keytypes for each CN/SAN
3146 * for example, if CN/SAN www.a.com is associated with
3147 * certs with keytype 0 and 2, then at the end of the loop,
3148 * www.a.com will have:
3149 * keyindex = 0 | 1 | 4 = 5
3150 */
3151 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3152
3153 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3154 continue;
3155
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003156 if (fcount) {
Willy Tarreau24b892f2016-06-20 23:01:57 +02003157 for (i = 0; i < fcount; i++)
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003158 ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3159 } else {
3160 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3161 * so the line that contains logic is marked via comments
3162 */
3163 xname = X509_get_subject_name(certs_and_keys[n].cert);
3164 i = -1;
3165 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3166 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003167 ASN1_STRING *value;
3168 value = X509_NAME_ENTRY_get_data(entry);
3169 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003170 /* Important line is here */
3171 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003172
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003173 OPENSSL_free(str);
3174 str = NULL;
3175 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003176 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003177
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003178 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003179#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003180 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3181 if (names) {
3182 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3183 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003184
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003185 if (name->type == GEN_DNS) {
3186 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3187 /* Important line is here */
3188 ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003189
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003190 OPENSSL_free(str);
3191 str = NULL;
3192 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003193 }
3194 }
3195 }
3196 }
3197#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3198 }
3199
3200 /* If no files found, return error */
3201 if (eb_is_empty(&sni_keytypes_map)) {
3202 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3203 err && *err ? *err : "", path);
3204 rv = 1;
3205 goto end;
3206 }
3207
3208 /* We now have a map of CN/SAN to keytypes that are loaded in
3209 * Iterate through the map to create the SSL_CTX's (if needed)
3210 * and add each CTX to the SNI tree
3211 *
3212 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003213 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003214 * combination is denoted by the key in the map. Each key
3215 * has a value between 1 and 2^n - 1. Conveniently, the array
3216 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3217 * entry in the array to correspond to the unique combo (key)
3218 * associated with i. This unique key combo (i) will be associated
3219 * with combos[i-1]
3220 */
3221
3222 node = ebmb_first(&sni_keytypes_map);
3223 while (node) {
3224 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003225 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003226 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003227
3228 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3229 i = container_of(node, struct sni_keytype, name)->keytypes;
3230 cur_ctx = key_combos[i-1].ctx;
3231
3232 if (cur_ctx == NULL) {
3233 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003234 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003235 if (cur_ctx == NULL) {
3236 memprintf(err, "%sunable to allocate SSL context.\n",
3237 err && *err ? *err : "");
3238 rv = 1;
3239 goto end;
3240 }
3241
yanbzhube2774d2015-12-10 15:07:30 -05003242 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003243 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3244 if (i & (1<<n)) {
3245 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003246 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3247 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003248 SSL_CTX_free(cur_ctx);
3249 rv = 1;
3250 goto end;
3251 }
yanbzhube2774d2015-12-10 15:07:30 -05003252
3253#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
3254 /* Load OCSP Info into context */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003255 if (ssl_sock_load_ocsp(cur_ctx, cur_file) < 0) {
yanbzhube2774d2015-12-10 15:07:30 -05003256 if (err)
3257 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 +00003258 *err ? *err : "", cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003259 SSL_CTX_free(cur_ctx);
3260 rv = 1;
3261 goto end;
3262 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003263#elif (defined OPENSSL_IS_BORINGSSL)
3264 ssl_sock_set_ocsp_response_from_file(cur_ctx, cur_file);
yanbzhube2774d2015-12-10 15:07:30 -05003265#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05003266 }
3267 }
3268
3269 /* Load DH params into the ctx to support DHE keys */
3270#ifndef OPENSSL_NO_DH
3271 if (ssl_dh_ptr_index >= 0)
3272 SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
3273
3274 rv = ssl_sock_load_dh_params(cur_ctx, NULL);
3275 if (rv < 0) {
3276 if (err)
3277 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3278 *err ? *err : "", path);
3279 rv = 1;
3280 goto end;
3281 }
3282#endif
3283
3284 /* Update key_combos */
3285 key_combos[i-1].ctx = cur_ctx;
3286 }
3287
3288 /* Update SNI Tree */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003289 key_combos[i-1].order = ssl_sock_add_cert_sni(cur_ctx, bind_conf, ssl_conf,
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003290 kinfo, str, key_combos[i-1].order);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003291 node = ebmb_next(node);
3292 }
3293
3294
3295 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3296 if (!bind_conf->default_ctx) {
3297 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3298 if (key_combos[i].ctx) {
3299 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003300 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003301 break;
3302 }
3303 }
3304 }
3305
3306end:
3307
3308 if (names)
3309 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3310
3311 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++)
3312 ssl_sock_free_cert_key_and_chain_contents(&certs_and_keys[n]);
3313
3314 node = ebmb_first(&sni_keytypes_map);
3315 while (node) {
3316 next = ebmb_next(node);
3317 ebmb_delete(node);
3318 node = next;
3319 }
3320
3321 return rv;
3322}
3323#else
3324/* This is a dummy, that just logs an error and returns error */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003325static int ssl_sock_load_multi_cert(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3326 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003327{
3328 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3329 err && *err ? *err : "", path, strerror(errno));
3330 return 1;
3331}
3332
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003333#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003334
Emeric Brunfc0421f2012-09-07 17:30:07 +02003335/* Loads a certificate key and CA chain from a file. Returns 0 on error, -1 if
3336 * an early error happens and the caller must call SSL_CTX_free() by itelf.
3337 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003338static int ssl_sock_load_cert_chain_file(SSL_CTX *ctx, const char *file, struct bind_conf *s,
3339 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003340{
3341 BIO *in;
3342 X509 *x = NULL, *ca;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003343 int i, err;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003344 int ret = -1;
3345 int order = 0;
3346 X509_NAME *xname;
3347 char *str;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003348 pem_password_cb *passwd_cb;
3349 void *passwd_cb_userdata;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003350 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003351 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003352
Emeric Brunfc0421f2012-09-07 17:30:07 +02003353#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3354 STACK_OF(GENERAL_NAME) *names;
3355#endif
3356
3357 in = BIO_new(BIO_s_file());
3358 if (in == NULL)
3359 goto end;
3360
3361 if (BIO_read_filename(in, file) <= 0)
3362 goto end;
3363
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003364
3365 passwd_cb = SSL_CTX_get_default_passwd_cb(ctx);
3366 passwd_cb_userdata = SSL_CTX_get_default_passwd_cb_userdata(ctx);
3367
3368 x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_cb_userdata);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003369 if (x == NULL)
3370 goto end;
3371
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003372 pkey = X509_get_pubkey(x);
3373 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003374 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003375 switch(EVP_PKEY_base_id(pkey)) {
3376 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003377 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003378 break;
3379 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003380 kinfo.sig = TLSEXT_signature_ecdsa;
3381 break;
3382 case EVP_PKEY_DSA:
3383 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003384 break;
3385 }
3386 EVP_PKEY_free(pkey);
3387 }
3388
Emeric Brun50bcecc2013-04-22 13:05:23 +02003389 if (fcount) {
3390 while (fcount--)
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003391 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, sni_filter[fcount], order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003392 }
3393 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003394#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003395 names = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
3396 if (names) {
3397 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3398 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3399 if (name->type == GEN_DNS) {
3400 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003401 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003402 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003403 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003404 }
3405 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003406 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003407 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003408#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003409 xname = X509_get_subject_name(x);
3410 i = -1;
3411 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3412 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003413 ASN1_STRING *value;
3414
3415 value = X509_NAME_ENTRY_get_data(entry);
3416 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003417 order = ssl_sock_add_cert_sni(ctx, s, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003418 OPENSSL_free(str);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003419 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003420 }
3421 }
3422
3423 ret = 0; /* the caller must not free the SSL_CTX argument anymore */
3424 if (!SSL_CTX_use_certificate(ctx, x))
3425 goto end;
3426
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003427#ifdef SSL_CTX_clear_extra_chain_certs
3428 SSL_CTX_clear_extra_chain_certs(ctx);
3429#else
Emeric Brunfc0421f2012-09-07 17:30:07 +02003430 if (ctx->extra_certs != NULL) {
3431 sk_X509_pop_free(ctx->extra_certs, X509_free);
3432 ctx->extra_certs = NULL;
3433 }
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003434#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003435
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003436 while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_cb_userdata))) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003437 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3438 X509_free(ca);
3439 goto end;
3440 }
3441 }
3442
3443 err = ERR_get_error();
3444 if (!err || (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
3445 /* we successfully reached the last cert in the file */
3446 ret = 1;
3447 }
3448 ERR_clear_error();
3449
3450end:
3451 if (x)
3452 X509_free(x);
3453
3454 if (in)
3455 BIO_free(in);
3456
3457 return ret;
3458}
3459
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003460static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3461 char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003462{
3463 int ret;
3464 SSL_CTX *ctx;
3465
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003466 ctx = SSL_CTX_new(SSLv23_server_method());
Emeric Brunfc0421f2012-09-07 17:30:07 +02003467 if (!ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003468 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3469 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003470 return 1;
3471 }
3472
3473 if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003474 memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
3475 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003476 SSL_CTX_free(ctx);
3477 return 1;
3478 }
3479
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003480 ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003481 if (ret <= 0) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003482 memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
3483 err && *err ? *err : "", path);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003484 if (ret < 0) /* serious error, must do that ourselves */
3485 SSL_CTX_free(ctx);
3486 return 1;
3487 }
Emeric Brun61694ab2012-10-26 13:35:33 +02003488
3489 if (SSL_CTX_check_private_key(ctx) <= 0) {
3490 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
3491 err && *err ? *err : "", path);
3492 return 1;
3493 }
3494
Emeric Brunfc0421f2012-09-07 17:30:07 +02003495 /* we must not free the SSL_CTX anymore below, since it's already in
3496 * the tree, so it will be discovered and cleaned in time.
3497 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003498#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +02003499 /* store a NULL pointer to indicate we have not yet loaded
3500 a custom DH param file */
3501 if (ssl_dh_ptr_index >= 0) {
3502 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3503 }
3504
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003505 ret = ssl_sock_load_dh_params(ctx, path);
3506 if (ret < 0) {
3507 if (err)
3508 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3509 *err ? *err : "", path);
3510 return 1;
3511 }
3512#endif
3513
Lukas Tribuse4e30f72014-12-09 16:32:51 +01003514#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4147b2e2014-06-16 18:36:30 +02003515 ret = ssl_sock_load_ocsp(ctx, path);
3516 if (ret < 0) {
3517 if (err)
3518 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",
3519 *err ? *err : "", path);
3520 return 1;
3521 }
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02003522#elif (defined OPENSSL_IS_BORINGSSL)
3523 ssl_sock_set_ocsp_response_from_file(ctx, path);
Emeric Brun4147b2e2014-06-16 18:36:30 +02003524#endif
3525
Willy Tarreau5db847a2019-05-09 14:13:35 +02003526#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01003527 if (sctl_ex_index >= 0) {
3528 ret = ssl_sock_load_sctl(ctx, path);
3529 if (ret < 0) {
3530 if (err)
3531 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3532 *err ? *err : "", path);
3533 return 1;
3534 }
3535 }
3536#endif
3537
Emeric Brunfc0421f2012-09-07 17:30:07 +02003538#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003539 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003540 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3541 err && *err ? *err : "");
Emeric Brunfc0421f2012-09-07 17:30:07 +02003542 return 1;
3543 }
3544#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003545 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003546 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003547 bind_conf->default_ssl_conf = ssl_conf;
3548 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003549
3550 return 0;
3551}
3552
Willy Tarreau03209342016-12-22 17:08:28 +01003553int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003554{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003555 struct dirent **de_list;
3556 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003557 DIR *dir;
3558 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003559 char *end;
3560 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003561 int cfgerr = 0;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003562#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003563 int is_bundle;
3564 int j;
3565#endif
Emeric Brunfc0421f2012-09-07 17:30:07 +02003566
yanbzhu08ce6ab2015-12-02 13:01:29 -05003567 if (stat(path, &buf) == 0) {
3568 dir = opendir(path);
3569 if (!dir)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003570 return ssl_sock_load_cert_file(path, bind_conf, NULL, NULL, 0, err);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003571
yanbzhu08ce6ab2015-12-02 13:01:29 -05003572 /* strip trailing slashes, including first one */
3573 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3574 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003575
yanbzhu08ce6ab2015-12-02 13:01:29 -05003576 n = scandir(path, &de_list, 0, alphasort);
3577 if (n < 0) {
3578 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3579 err && *err ? *err : "", path, strerror(errno));
3580 cfgerr++;
3581 }
3582 else {
3583 for (i = 0; i < n; i++) {
3584 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003585
yanbzhu08ce6ab2015-12-02 13:01:29 -05003586 end = strrchr(de->d_name, '.');
3587 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3588 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003589
yanbzhu08ce6ab2015-12-02 13:01:29 -05003590 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3591 if (stat(fp, &buf) != 0) {
3592 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3593 err && *err ? *err : "", fp, strerror(errno));
3594 cfgerr++;
3595 goto ignore_entry;
3596 }
3597 if (!S_ISREG(buf.st_mode))
3598 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003599
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003600#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003601 is_bundle = 0;
3602 /* Check if current entry in directory is part of a multi-cert bundle */
3603
3604 if (end) {
3605 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3606 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3607 is_bundle = 1;
3608 break;
3609 }
3610 }
3611
3612 if (is_bundle) {
3613 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3614 int dp_len;
3615
3616 dp_len = end - de->d_name;
3617 snprintf(dp, dp_len + 1, "%s", de->d_name);
3618
3619 /* increment i and free de until we get to a non-bundle cert
3620 * Note here that we look at de_list[i + 1] before freeing de
3621 * this is important since ignore_entry will free de
3622 */
3623 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3624 free(de);
3625 i++;
3626 de = de_list[i];
3627 }
3628
3629 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
Emeric Bruneb155b62018-08-16 15:11:12 +02003630 cfgerr += ssl_sock_load_multi_cert(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003631
3632 /* Successfully processed the bundle */
3633 goto ignore_entry;
3634 }
3635 }
3636
3637#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003638 cfgerr += ssl_sock_load_cert_file(fp, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003639ignore_entry:
3640 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003641 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003642 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003643 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003644 closedir(dir);
3645 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003646 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003647
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003648 cfgerr = ssl_sock_load_multi_cert(path, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003649
Emeric Brunfc0421f2012-09-07 17:30:07 +02003650 return cfgerr;
3651}
3652
Thierry Fournier383085f2013-01-24 14:15:43 +01003653/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3654 * done once. Zero is returned if the operation fails. No error is returned
3655 * if the random is said as not implemented, because we expect that openssl
3656 * will use another method once needed.
3657 */
3658static int ssl_initialize_random()
3659{
3660 unsigned char random;
3661 static int random_initialized = 0;
3662
3663 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3664 random_initialized = 1;
3665
3666 return random_initialized;
3667}
3668
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003669/* release ssl bind conf */
3670void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003671{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003672 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003673#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003674 free(conf->npn_str);
3675 conf->npn_str = NULL;
3676#endif
3677#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3678 free(conf->alpn_str);
3679 conf->alpn_str = NULL;
3680#endif
3681 free(conf->ca_file);
3682 conf->ca_file = NULL;
3683 free(conf->crl_file);
3684 conf->crl_file = NULL;
3685 free(conf->ciphers);
3686 conf->ciphers = NULL;
Willy Tarreau5db847a2019-05-09 14:13:35 +02003687#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003688 free(conf->ciphersuites);
3689 conf->ciphersuites = NULL;
3690#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003691 free(conf->curves);
3692 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003693 free(conf->ecdhe);
3694 conf->ecdhe = NULL;
3695 }
3696}
3697
3698int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3699{
3700 char thisline[CRT_LINESIZE];
3701 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003702 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003703 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003704 int linenum = 0;
3705 int cfgerr = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003706
Willy Tarreauad1731d2013-04-02 17:35:58 +02003707 if ((f = fopen(file, "r")) == NULL) {
3708 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003709 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003710 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003711
3712 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003713 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003714 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003715 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003716 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003717 char *crt_path;
3718 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003719
3720 linenum++;
3721 end = line + strlen(line);
3722 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3723 /* Check if we reached the limit and the last char is not \n.
3724 * Watch out for the last line without the terminating '\n'!
3725 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003726 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3727 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003728 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003729 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003730 }
3731
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003732 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003733 newarg = 1;
3734 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003735 if (*line == '#' || *line == '\n' || *line == '\r') {
3736 /* end of string, end of loop */
3737 *line = 0;
3738 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003739 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003740 newarg = 1;
3741 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003742 } else if (*line == '[') {
3743 if (ssl_b) {
3744 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3745 cfgerr = 1;
3746 break;
3747 }
3748 if (!arg) {
3749 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3750 cfgerr = 1;
3751 break;
3752 }
3753 ssl_b = arg;
3754 newarg = 1;
3755 *line = 0;
3756 } else if (*line == ']') {
3757 if (ssl_e) {
3758 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003759 cfgerr = 1;
3760 break;
3761 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003762 if (!ssl_b) {
3763 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3764 cfgerr = 1;
3765 break;
3766 }
3767 ssl_e = arg;
3768 newarg = 1;
3769 *line = 0;
3770 } else if (newarg) {
3771 if (arg == MAX_CRT_ARGS) {
3772 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3773 cfgerr = 1;
3774 break;
3775 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003776 newarg = 0;
3777 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003778 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003779 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003780 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003781 if (cfgerr)
3782 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003783 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003784
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003785 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003786 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003787 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003788
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003789 crt_path = args[0];
3790 if (*crt_path != '/' && global_ssl.crt_base) {
3791 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3792 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3793 crt_path, linenum, file);
3794 cfgerr = 1;
3795 break;
3796 }
3797 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3798 crt_path = path;
3799 }
3800
3801 ssl_conf = calloc(1, sizeof *ssl_conf);
3802 cur_arg = ssl_b ? ssl_b : 1;
3803 while (cur_arg < ssl_e) {
3804 newarg = 0;
3805 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3806 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3807 newarg = 1;
3808 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3809 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3810 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3811 args[cur_arg], linenum, file);
3812 cfgerr = 1;
3813 }
3814 cur_arg += 1 + ssl_bind_kws[i].skip;
3815 break;
3816 }
3817 }
3818 if (!cfgerr && !newarg) {
3819 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3820 args[cur_arg], linenum, file);
3821 cfgerr = 1;
3822 break;
3823 }
3824 }
3825 if (cfgerr) {
3826 ssl_sock_free_ssl_conf(ssl_conf);
3827 free(ssl_conf);
3828 ssl_conf = NULL;
3829 break;
3830 }
3831
3832 if (stat(crt_path, &buf) == 0) {
3833 cfgerr = ssl_sock_load_cert_file(crt_path, bind_conf, ssl_conf,
3834 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003835 } else {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003836 cfgerr = ssl_sock_load_multi_cert(crt_path, bind_conf, ssl_conf,
3837 &args[cur_arg], arg - cur_arg - 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05003838 }
3839
Willy Tarreauad1731d2013-04-02 17:35:58 +02003840 if (cfgerr) {
3841 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003842 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003843 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003844 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003845 fclose(f);
3846 return cfgerr;
3847}
3848
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003849/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003850static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003851ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003852{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003853 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003854 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003855 SSL_OP_ALL | /* all known workarounds for bugs */
3856 SSL_OP_NO_SSLv2 |
3857 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003858 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02003859 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003860 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02003861 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02003862 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003863 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02003864 SSL_MODE_ENABLE_PARTIAL_WRITE |
3865 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01003866 SSL_MODE_RELEASE_BUFFERS |
3867 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02003868 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003869 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003870 int flags = MC_SSL_O_ALL;
3871 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003872
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003873 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003874 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003875
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003876 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01003877 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
3878 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3879 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003880 else
3881 flags = conf_ssl_methods->flags;
3882
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003883 min = conf_ssl_methods->min;
3884 max = conf_ssl_methods->max;
3885 /* start with TLSv10 to remove SSLv3 per default */
3886 if (!min && (!max || max >= CONF_TLSV10))
3887 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003888 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02003889 if (min)
3890 flags |= (methodVersions[min].flag - 1);
3891 if (max)
3892 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003893 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003894 min = max = CONF_TLSV_NONE;
3895 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003896 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003897 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003898 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003899 if (min) {
3900 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003901 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
3902 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
3903 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
3904 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003905 hole = 0;
3906 }
3907 max = i;
3908 }
3909 else {
3910 min = max = i;
3911 }
3912 }
3913 else {
3914 if (min)
3915 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003916 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003917 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003918 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
3919 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003920 cfgerr += 1;
3921 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02003922 /* save real min/max in bind_conf */
3923 conf_ssl_methods->min = min;
3924 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003925
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003926#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003927 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08003928 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003929 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003930 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003931 else
3932 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
3933 if (flags & methodVersions[i].flag)
3934 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003935#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02003936 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02003937 methodVersions[min].ctx_set_version(ctx, SET_MIN);
3938 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02003939#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003940
3941 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
3942 options |= SSL_OP_NO_TICKET;
3943 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
3944 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08003945
3946#ifdef SSL_OP_NO_RENEGOTIATION
3947 options |= SSL_OP_NO_RENEGOTIATION;
3948#endif
3949
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003950 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003951
Willy Tarreau5db847a2019-05-09 14:13:35 +02003952#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00003953 if (global_ssl.async)
3954 mode |= SSL_MODE_ASYNC;
3955#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02003956 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003957 if (global_ssl.life_time)
3958 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003959
3960#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3961#ifdef OPENSSL_IS_BORINGSSL
3962 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
3963 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02003964#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01003965 if (bind_conf->ssl_conf.early_data) {
3966 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
3967 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
3968 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02003969 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
3970 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003971#else
3972 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003973#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02003974 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003975#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02003976 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01003977}
3978
William Lallemand4f45bb92017-10-30 20:08:51 +01003979
3980static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
3981{
3982 if (first == block) {
3983 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
3984 if (first->len > 0)
3985 sh_ssl_sess_tree_delete(sh_ssl_sess);
3986 }
3987}
3988
3989/* return first block from sh_ssl_sess */
3990static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
3991{
3992 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
3993
3994}
3995
3996/* store a session into the cache
3997 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
3998 * data: asn1 encoded session
3999 * data_len: asn1 encoded session length
4000 * Returns 1 id session was stored (else 0)
4001 */
4002static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4003{
4004 struct shared_block *first;
4005 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4006
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004007 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004008 if (!first) {
4009 /* Could not retrieve enough free blocks to store that session */
4010 return 0;
4011 }
4012
4013 /* STORE the key in the first elem */
4014 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4015 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4016 first->len = sizeof(struct sh_ssl_sess_hdr);
4017
4018 /* it returns the already existing node
4019 or current node if none, never returns null */
4020 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4021 if (oldsh_ssl_sess != sh_ssl_sess) {
4022 /* NOTE: Row couldn't be in use because we lock read & write function */
4023 /* release the reserved row */
4024 shctx_row_dec_hot(ssl_shctx, first);
4025 /* replace the previous session already in the tree */
4026 sh_ssl_sess = oldsh_ssl_sess;
4027 /* ignore the previous session data, only use the header */
4028 first = sh_ssl_sess_first_block(sh_ssl_sess);
4029 shctx_row_inc_hot(ssl_shctx, first);
4030 first->len = sizeof(struct sh_ssl_sess_hdr);
4031 }
4032
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004033 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004034 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004035 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004036 }
4037
4038 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004039
4040 return 1;
4041}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004042
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004043/* SSL callback used when a new session is created while connecting to a server */
4044static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4045{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004046 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004047 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004048
Willy Tarreau07d94e42018-09-20 10:57:52 +02004049 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004050
Olivier Houcharde6060c52017-11-16 17:42:52 +01004051 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4052 int len;
4053 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004054
Olivier Houcharde6060c52017-11-16 17:42:52 +01004055 len = i2d_SSL_SESSION(sess, NULL);
4056 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4057 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4058 } else {
4059 free(s->ssl_ctx.reused_sess[tid].ptr);
4060 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4061 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4062 }
4063 if (s->ssl_ctx.reused_sess[tid].ptr) {
4064 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4065 &ptr);
4066 }
4067 } else {
4068 free(s->ssl_ctx.reused_sess[tid].ptr);
4069 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4070 }
4071
4072 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004073}
4074
Olivier Houcharde6060c52017-11-16 17:42:52 +01004075
William Lallemanded0b5ad2017-10-30 19:36:36 +01004076/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004077int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004078{
4079 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4080 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4081 unsigned char *p;
4082 int data_len;
4083 unsigned int sid_length, sid_ctx_length;
4084 const unsigned char *sid_data;
4085 const unsigned char *sid_ctx_data;
4086
4087 /* Session id is already stored in to key and session id is known
4088 * so we dont store it to keep size.
4089 */
4090
4091 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4092 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4093 SSL_SESSION_set1_id(sess, sid_data, 0);
4094 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4095
4096 /* check if buffer is large enough for the ASN1 encoded session */
4097 data_len = i2d_SSL_SESSION(sess, NULL);
4098 if (data_len > SHSESS_MAX_DATA_LEN)
4099 goto err;
4100
4101 p = encsess;
4102
4103 /* process ASN1 session encoding before the lock */
4104 i2d_SSL_SESSION(sess, &p);
4105
4106 memcpy(encid, sid_data, sid_length);
4107 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4108 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4109
William Lallemanda3c77cf2017-10-30 23:44:40 +01004110 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004111 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004112 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004113 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004114err:
4115 /* reset original length values */
4116 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4117 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4118
4119 return 0; /* do not increment session reference count */
4120}
4121
4122/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004123SSL_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 +01004124{
William Lallemand4f45bb92017-10-30 20:08:51 +01004125 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004126 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4127 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004128 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004129 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004130
4131 global.shctx_lookups++;
4132
4133 /* allow the session to be freed automatically by openssl */
4134 *do_copy = 0;
4135
4136 /* tree key is zeros padded sessionid */
4137 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4138 memcpy(tmpkey, key, key_len);
4139 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4140 key = tmpkey;
4141 }
4142
4143 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004144 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004145
4146 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004147 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4148 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004149 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004150 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004151 global.shctx_misses++;
4152 return NULL;
4153 }
4154
William Lallemand4f45bb92017-10-30 20:08:51 +01004155 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4156 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004157
William Lallemand4f45bb92017-10-30 20:08:51 +01004158 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 +01004159
William Lallemanda3c77cf2017-10-30 23:44:40 +01004160 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004161
4162 /* decode ASN1 session */
4163 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004164 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004165 /* Reset session id and session id contenxt */
4166 if (sess) {
4167 SSL_SESSION_set1_id(sess, key, key_len);
4168 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4169 }
4170
4171 return sess;
4172}
4173
William Lallemand4f45bb92017-10-30 20:08:51 +01004174
William Lallemanded0b5ad2017-10-30 19:36:36 +01004175/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004176void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004177{
William Lallemand4f45bb92017-10-30 20:08:51 +01004178 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004179 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4180 unsigned int sid_length;
4181 const unsigned char *sid_data;
4182 (void)ctx;
4183
4184 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4185 /* tree key is zeros padded sessionid */
4186 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4187 memcpy(tmpkey, sid_data, sid_length);
4188 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4189 sid_data = tmpkey;
4190 }
4191
William Lallemanda3c77cf2017-10-30 23:44:40 +01004192 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004193
4194 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004195 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4196 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004197 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004198 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004199 }
4200
4201 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004202 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004203}
4204
4205/* Set session cache mode to server and disable openssl internal cache.
4206 * Set shared cache callbacks on an ssl context.
4207 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004208void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004209{
4210 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4211
4212 if (!ssl_shctx) {
4213 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4214 return;
4215 }
4216
4217 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4218 SSL_SESS_CACHE_NO_INTERNAL |
4219 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4220
4221 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004222 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4223 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4224 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004225}
4226
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004227int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4228{
4229 struct proxy *curproxy = bind_conf->frontend;
4230 int cfgerr = 0;
4231 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004232 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004233 const char *conf_ciphers;
Willy Tarreau5db847a2019-05-09 14:13:35 +02004234#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004235 const char *conf_ciphersuites;
4236#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004237 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004238
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004239 if (ssl_conf) {
4240 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4241 int i, min, max;
4242 int flags = MC_SSL_O_ALL;
4243
4244 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004245 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4246 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004247 if (min)
4248 flags |= (methodVersions[min].flag - 1);
4249 if (max)
4250 flags |= ~((methodVersions[max].flag << 1) - 1);
4251 min = max = CONF_TLSV_NONE;
4252 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4253 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4254 if (min)
4255 max = i;
4256 else
4257 min = max = i;
4258 }
4259 /* save real min/max */
4260 conf_ssl_methods->min = min;
4261 conf_ssl_methods->max = max;
4262 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004263 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4264 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004265 cfgerr += 1;
4266 }
4267 }
4268
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004269 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004270 case SSL_SOCK_VERIFY_NONE:
4271 verify = SSL_VERIFY_NONE;
4272 break;
4273 case SSL_SOCK_VERIFY_OPTIONAL:
4274 verify = SSL_VERIFY_PEER;
4275 break;
4276 case SSL_SOCK_VERIFY_REQUIRED:
4277 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4278 break;
4279 }
4280 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4281 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004282 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4283 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4284 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004285 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004286 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004287 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4288 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004289 cfgerr++;
4290 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004291 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4292 /* set CA names for client cert request, function returns void */
4293 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4294 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004295 }
Emeric Brun850efd52014-01-29 12:24:34 +01004296 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004297 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4298 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004299 cfgerr++;
4300 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004301#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004302 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004303 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4304
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004305 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004306 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4307 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004308 cfgerr++;
4309 }
Emeric Brun561e5742012-10-02 15:20:55 +02004310 else {
4311 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4312 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004313 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004314#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004315 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004316 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004317#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004318 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004319 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004320 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4321 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004322 cfgerr++;
4323 }
4324 }
4325#endif
4326
William Lallemand4f45bb92017-10-30 20:08:51 +01004327 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004328 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4329 if (conf_ciphers &&
4330 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004331 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4332 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004333 cfgerr++;
4334 }
4335
Willy Tarreau5db847a2019-05-09 14:13:35 +02004336#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004337 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4338 if (conf_ciphersuites &&
4339 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4340 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4341 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4342 cfgerr++;
4343 }
4344#endif
4345
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004346#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004347 /* If tune.ssl.default-dh-param has not been set,
4348 neither has ssl-default-dh-file and no static DH
4349 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004350 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004351 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004352 (ssl_dh_ptr_index == -1 ||
4353 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004354 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4355 const SSL_CIPHER * cipher = NULL;
4356 char cipher_description[128];
4357 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4358 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4359 which is not ephemeral DH. */
4360 const char dhe_description[] = " Kx=DH ";
4361 const char dhe_export_description[] = " Kx=DH(";
4362 int idx = 0;
4363 int dhe_found = 0;
4364 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004365
Remi Gacogne23d5d372014-10-10 17:04:26 +02004366 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004367
Remi Gacogne23d5d372014-10-10 17:04:26 +02004368 if (ssl) {
4369 ciphers = SSL_get_ciphers(ssl);
4370
4371 if (ciphers) {
4372 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4373 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4374 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4375 if (strstr(cipher_description, dhe_description) != NULL ||
4376 strstr(cipher_description, dhe_export_description) != NULL) {
4377 dhe_found = 1;
4378 break;
4379 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004380 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004381 }
4382 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004383 SSL_free(ssl);
4384 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004385 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004386
Lukas Tribus90132722014-08-18 00:56:33 +02004387 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004388 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 +02004389 }
4390
Willy Tarreauef934602016-12-22 23:12:01 +01004391 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004392 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004393
Willy Tarreauef934602016-12-22 23:12:01 +01004394 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004395 if (local_dh_1024 == NULL) {
4396 local_dh_1024 = ssl_get_dh_1024();
4397 }
Willy Tarreauef934602016-12-22 23:12:01 +01004398 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004399 if (local_dh_2048 == NULL) {
4400 local_dh_2048 = ssl_get_dh_2048();
4401 }
Willy Tarreauef934602016-12-22 23:12:01 +01004402 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004403 if (local_dh_4096 == NULL) {
4404 local_dh_4096 = ssl_get_dh_4096();
4405 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004406 }
4407 }
4408 }
4409#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004410
Emeric Brunfc0421f2012-09-07 17:30:07 +02004411 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004412#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004413 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004414#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004415
Bernard Spil13c53f82018-02-15 13:34:58 +01004416#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004417 ssl_conf_cur = NULL;
4418 if (ssl_conf && ssl_conf->npn_str)
4419 ssl_conf_cur = ssl_conf;
4420 else if (bind_conf->ssl_conf.npn_str)
4421 ssl_conf_cur = &bind_conf->ssl_conf;
4422 if (ssl_conf_cur)
4423 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004424#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004425#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004426 ssl_conf_cur = NULL;
4427 if (ssl_conf && ssl_conf->alpn_str)
4428 ssl_conf_cur = ssl_conf;
4429 else if (bind_conf->ssl_conf.alpn_str)
4430 ssl_conf_cur = &bind_conf->ssl_conf;
4431 if (ssl_conf_cur)
4432 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004433#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004434#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004435 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4436 if (conf_curves) {
4437 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004438 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4439 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004440 cfgerr++;
4441 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004442#if defined(SSL_CTX_set_ecdh_auto)
4443 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4444#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004445 }
4446#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004447#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004448 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004449 int i;
4450 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004451#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004452 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004453 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4454 NULL);
4455
4456 if (ecdhe == NULL) {
4457 SSL_CTX_set_dh_auto(ctx, 1);
4458 return cfgerr;
4459 }
4460#else
4461 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4462 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4463 ECDHE_DEFAULT_CURVE);
4464#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004465
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004466 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004467 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004468 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4469 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004470 cfgerr++;
4471 }
4472 else {
4473 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4474 EC_KEY_free(ecdh);
4475 }
4476 }
4477#endif
4478
Emeric Brunfc0421f2012-09-07 17:30:07 +02004479 return cfgerr;
4480}
4481
Evan Broderbe554312013-06-27 00:05:25 -07004482static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4483{
4484 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4485 size_t prefixlen, suffixlen;
4486
4487 /* Trivial case */
4488 if (strcmp(pattern, hostname) == 0)
4489 return 1;
4490
Evan Broderbe554312013-06-27 00:05:25 -07004491 /* The rest of this logic is based on RFC 6125, section 6.4.3
4492 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4493
Emeric Bruna848dae2013-10-08 11:27:28 +02004494 pattern_wildcard = NULL;
4495 pattern_left_label_end = pattern;
4496 while (*pattern_left_label_end != '.') {
4497 switch (*pattern_left_label_end) {
4498 case 0:
4499 /* End of label not found */
4500 return 0;
4501 case '*':
4502 /* If there is more than one wildcards */
4503 if (pattern_wildcard)
4504 return 0;
4505 pattern_wildcard = pattern_left_label_end;
4506 break;
4507 }
4508 pattern_left_label_end++;
4509 }
4510
4511 /* If it's not trivial and there is no wildcard, it can't
4512 * match */
4513 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004514 return 0;
4515
4516 /* Make sure all labels match except the leftmost */
4517 hostname_left_label_end = strchr(hostname, '.');
4518 if (!hostname_left_label_end
4519 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4520 return 0;
4521
4522 /* Make sure the leftmost label of the hostname is long enough
4523 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004524 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004525 return 0;
4526
4527 /* Finally compare the string on either side of the
4528 * wildcard */
4529 prefixlen = pattern_wildcard - pattern;
4530 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004531 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4532 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004533 return 0;
4534
4535 return 1;
4536}
4537
4538static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4539{
4540 SSL *ssl;
4541 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004542 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004543 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004544 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004545
4546 int depth;
4547 X509 *cert;
4548 STACK_OF(GENERAL_NAME) *alt_names;
4549 int i;
4550 X509_NAME *cert_subject;
4551 char *str;
4552
4553 if (ok == 0)
4554 return ok;
4555
4556 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004557 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004558 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004559
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004560 /* We're checking if the provided hostnames match the desired one. The
4561 * desired hostname comes from the SNI we presented if any, or if not
4562 * provided then it may have been explicitly stated using a "verifyhost"
4563 * directive. If neither is set, we don't care about the name so the
4564 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004565 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004566 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004567 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004568 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004569 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004570 if (!servername)
4571 return ok;
4572 }
Evan Broderbe554312013-06-27 00:05:25 -07004573
4574 /* We only need to verify the CN on the actual server cert,
4575 * not the indirect CAs */
4576 depth = X509_STORE_CTX_get_error_depth(ctx);
4577 if (depth != 0)
4578 return ok;
4579
4580 /* At this point, the cert is *not* OK unless we can find a
4581 * hostname match */
4582 ok = 0;
4583
4584 cert = X509_STORE_CTX_get_current_cert(ctx);
4585 /* It seems like this might happen if verify peer isn't set */
4586 if (!cert)
4587 return ok;
4588
4589 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4590 if (alt_names) {
4591 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4592 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4593 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004594#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004595 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4596#else
Evan Broderbe554312013-06-27 00:05:25 -07004597 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004598#endif
Evan Broderbe554312013-06-27 00:05:25 -07004599 ok = ssl_sock_srv_hostcheck(str, servername);
4600 OPENSSL_free(str);
4601 }
4602 }
4603 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004604 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004605 }
4606
4607 cert_subject = X509_get_subject_name(cert);
4608 i = -1;
4609 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4610 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004611 ASN1_STRING *value;
4612 value = X509_NAME_ENTRY_get_data(entry);
4613 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004614 ok = ssl_sock_srv_hostcheck(str, servername);
4615 OPENSSL_free(str);
4616 }
4617 }
4618
Willy Tarreau71d058c2017-07-26 20:09:56 +02004619 /* report the mismatch and indicate if SNI was used or not */
4620 if (!ok && !conn->err_code)
4621 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004622 return ok;
4623}
4624
Emeric Brun94324a42012-10-11 14:00:19 +02004625/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004626int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004627{
Willy Tarreau03209342016-12-22 17:08:28 +01004628 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004629 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004630 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004631 SSL_OP_ALL | /* all known workarounds for bugs */
4632 SSL_OP_NO_SSLv2 |
4633 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004634 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004635 SSL_MODE_ENABLE_PARTIAL_WRITE |
4636 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004637 SSL_MODE_RELEASE_BUFFERS |
4638 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004639 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004640 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004641 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004642 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004643 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004644
Thierry Fournier383085f2013-01-24 14:15:43 +01004645 /* Make sure openssl opens /dev/urandom before the chroot */
4646 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004647 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004648 cfgerr++;
4649 }
4650
Willy Tarreaufce03112015-01-15 21:32:40 +01004651 /* Automatic memory computations need to know we use SSL there */
4652 global.ssl_used_backend = 1;
4653
4654 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004655 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004656 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004657 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4658 curproxy->id, srv->id,
4659 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004660 cfgerr++;
4661 return cfgerr;
4662 }
4663 }
Emeric Brun94324a42012-10-11 14:00:19 +02004664 if (srv->use_ssl)
4665 srv->xprt = &ssl_sock;
4666 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004667 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004668
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004669 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004670 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004671 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4672 proxy_type_str(curproxy), curproxy->id,
4673 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004674 cfgerr++;
4675 return cfgerr;
4676 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004677
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004678 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004679 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4680 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4681 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004682 else
4683 flags = conf_ssl_methods->flags;
4684
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004685 /* Real min and max should be determinate with configuration and openssl's capabilities */
4686 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004687 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004688 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004689 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004690
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004691 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004692 min = max = CONF_TLSV_NONE;
4693 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004694 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004695 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004696 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004697 if (min) {
4698 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004699 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4700 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4701 proxy_type_str(curproxy), curproxy->id, srv->id,
4702 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004703 hole = 0;
4704 }
4705 max = i;
4706 }
4707 else {
4708 min = max = i;
4709 }
4710 }
4711 else {
4712 if (min)
4713 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004714 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004715 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004716 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4717 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004718 cfgerr += 1;
4719 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004720
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004721#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004722 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004723 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004724 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004725 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004726 else
4727 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4728 if (flags & methodVersions[i].flag)
4729 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004730#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004731 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004732 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4733 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004734#endif
4735
4736 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4737 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004738 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004739
Willy Tarreau5db847a2019-05-09 14:13:35 +02004740#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004741 if (global_ssl.async)
4742 mode |= SSL_MODE_ASYNC;
4743#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004744 SSL_CTX_set_mode(ctx, mode);
4745 srv->ssl_ctx.ctx = ctx;
4746
Emeric Bruna7aa3092012-10-26 12:58:00 +02004747 if (srv->ssl_ctx.client_crt) {
4748 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 +01004749 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4750 proxy_type_str(curproxy), curproxy->id,
4751 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004752 cfgerr++;
4753 }
4754 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 +01004755 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4756 proxy_type_str(curproxy), curproxy->id,
4757 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004758 cfgerr++;
4759 }
4760 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004761 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4762 proxy_type_str(curproxy), curproxy->id,
4763 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004764 cfgerr++;
4765 }
4766 }
Emeric Brun94324a42012-10-11 14:00:19 +02004767
Emeric Brun850efd52014-01-29 12:24:34 +01004768 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4769 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004770 switch (srv->ssl_ctx.verify) {
4771 case SSL_SOCK_VERIFY_NONE:
4772 verify = SSL_VERIFY_NONE;
4773 break;
4774 case SSL_SOCK_VERIFY_REQUIRED:
4775 verify = SSL_VERIFY_PEER;
4776 break;
4777 }
Evan Broderbe554312013-06-27 00:05:25 -07004778 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004779 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004780 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004781 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004782 if (srv->ssl_ctx.ca_file) {
4783 /* load CAfile to verify */
4784 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004785 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4786 curproxy->id, srv->id,
4787 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004788 cfgerr++;
4789 }
4790 }
Emeric Brun850efd52014-01-29 12:24:34 +01004791 else {
4792 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004793 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",
4794 curproxy->id, srv->id,
4795 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004796 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004797 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4798 curproxy->id, srv->id,
4799 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004800 cfgerr++;
4801 }
Emeric Brunef42d922012-10-11 16:11:36 +02004802#ifdef X509_V_FLAG_CRL_CHECK
4803 if (srv->ssl_ctx.crl_file) {
4804 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4805
4806 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004807 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4808 curproxy->id, srv->id,
4809 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004810 cfgerr++;
4811 }
4812 else {
4813 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4814 }
4815 }
4816#endif
4817 }
4818
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004819 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4820 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4821 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004822 if (srv->ssl_ctx.ciphers &&
4823 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004824 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
4825 curproxy->id, srv->id,
4826 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02004827 cfgerr++;
4828 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004829
Willy Tarreau5db847a2019-05-09 14:13:35 +02004830#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004831 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00004832 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004833 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
4834 curproxy->id, srv->id,
4835 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
4836 cfgerr++;
4837 }
4838#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01004839#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4840 if (srv->ssl_ctx.npn_str)
4841 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
4842#endif
4843#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4844 if (srv->ssl_ctx.alpn_str)
4845 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
4846#endif
4847
Emeric Brun94324a42012-10-11 14:00:19 +02004848
4849 return cfgerr;
4850}
4851
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004852/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004853 * be NULL, in which case nothing is done. Returns the number of errors
4854 * encountered.
4855 */
Willy Tarreau03209342016-12-22 17:08:28 +01004856int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004857{
4858 struct ebmb_node *node;
4859 struct sni_ctx *sni;
4860 int err = 0;
4861
Willy Tarreaufce03112015-01-15 21:32:40 +01004862 /* Automatic memory computations need to know we use SSL there */
4863 global.ssl_used_frontend = 1;
4864
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004865 /* Make sure openssl opens /dev/urandom before the chroot */
4866 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004867 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004868 err++;
4869 }
4870 /* Create initial_ctx used to start the ssl connection before do switchctx */
4871 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004872 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004873 /* It should not be necessary to call this function, but it's
4874 necessary first to check and move all initialisation related
4875 to initial_ctx in ssl_sock_initial_ctx. */
4876 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
4877 }
Emeric Brun0bed9942014-10-30 19:25:24 +01004878 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004879 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01004880
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004881 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004882 while (node) {
4883 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004884 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4885 /* only initialize the CTX on its first occurrence and
4886 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004887 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004888 node = ebmb_next(node);
4889 }
4890
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004891 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004892 while (node) {
4893 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01004894 if (!sni->order && sni->ctx != bind_conf->default_ctx)
4895 /* only initialize the CTX on its first occurrence and
4896 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004897 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004898 node = ebmb_next(node);
4899 }
4900 return err;
4901}
4902
Willy Tarreau55d37912016-12-21 23:38:39 +01004903/* Prepares all the contexts for a bind_conf and allocates the shared SSL
4904 * context if needed. Returns < 0 on error, 0 on success. The warnings and
4905 * alerts are directly emitted since the rest of the stack does it below.
4906 */
4907int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
4908{
4909 struct proxy *px = bind_conf->frontend;
4910 int alloc_ctx;
4911 int err;
4912
4913 if (!bind_conf->is_ssl) {
4914 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004915 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
4916 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01004917 }
4918 return 0;
4919 }
4920 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004921 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004922 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
4923 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004924 }
4925 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004926 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
4927 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02004928 return -1;
4929 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004930 }
William Lallemandc61c0b32017-12-04 18:46:39 +01004931 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004932 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02004933 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01004934 sizeof(*sh_ssl_sess_tree),
4935 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02004936 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01004937 if (alloc_ctx == SHCTX_E_INIT_LOCK)
4938 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");
4939 else
4940 ha_alert("Unable to allocate SSL session cache.\n");
4941 return -1;
4942 }
4943 /* free block callback */
4944 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
4945 /* init the root tree within the extra space */
4946 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
4947 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01004948 }
Willy Tarreau55d37912016-12-21 23:38:39 +01004949 err = 0;
4950 /* initialize all certificate contexts */
4951 err += ssl_sock_prepare_all_ctx(bind_conf);
4952
4953 /* initialize CA variables if the certificates generation is enabled */
4954 err += ssl_sock_load_ca(bind_conf);
4955
4956 return -err;
4957}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004958
4959/* release ssl context allocated for servers. */
4960void ssl_sock_free_srv_ctx(struct server *srv)
4961{
Olivier Houchardc7566002018-11-20 23:33:50 +01004962#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
4963 if (srv->ssl_ctx.alpn_str)
4964 free(srv->ssl_ctx.alpn_str);
4965#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01004966#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01004967 if (srv->ssl_ctx.npn_str)
4968 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01004969#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02004970 if (srv->ssl_ctx.ctx)
4971 SSL_CTX_free(srv->ssl_ctx.ctx);
4972}
4973
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004974/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02004975 * be NULL, in which case nothing is done. The default_ctx is nullified too.
4976 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004977void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004978{
4979 struct ebmb_node *node, *back;
4980 struct sni_ctx *sni;
4981
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004982 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004983 while (node) {
4984 sni = ebmb_entry(node, struct sni_ctx, name);
4985 back = ebmb_next(node);
4986 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004987 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02004988 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004989 ssl_sock_free_ssl_conf(sni->conf);
4990 free(sni->conf);
4991 sni->conf = NULL;
4992 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02004993 free(sni);
4994 node = back;
4995 }
4996
Willy Tarreau2a65ff02012-09-13 17:54:29 +02004997 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004998 while (node) {
4999 sni = ebmb_entry(node, struct sni_ctx, name);
5000 back = ebmb_next(node);
5001 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005002 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005003 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005004 ssl_sock_free_ssl_conf(sni->conf);
5005 free(sni->conf);
5006 sni->conf = NULL;
5007 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005008 free(sni);
5009 node = back;
5010 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005011 SSL_CTX_free(bind_conf->initial_ctx);
5012 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005013 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005014 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005015}
5016
Willy Tarreau795cdab2016-12-22 17:30:54 +01005017/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5018void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5019{
5020 ssl_sock_free_ca(bind_conf);
5021 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005022 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005023 free(bind_conf->ca_sign_file);
5024 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005025 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005026 free(bind_conf->keys_ref->filename);
5027 free(bind_conf->keys_ref->tlskeys);
5028 LIST_DEL(&bind_conf->keys_ref->list);
5029 free(bind_conf->keys_ref);
5030 }
5031 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005032 bind_conf->ca_sign_pass = NULL;
5033 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005034}
5035
Christopher Faulet31af49d2015-06-09 17:29:50 +02005036/* Load CA cert file and private key used to generate certificates */
5037int
Willy Tarreau03209342016-12-22 17:08:28 +01005038ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005039{
Willy Tarreau03209342016-12-22 17:08:28 +01005040 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005041 FILE *fp;
5042 X509 *cacert = NULL;
5043 EVP_PKEY *capkey = NULL;
5044 int err = 0;
5045
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005046 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005047 return err;
5048
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005049#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005050 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005051 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005052 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005053 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005054 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005055#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005056
Christopher Faulet31af49d2015-06-09 17:29:50 +02005057 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005058 ha_alert("Proxy '%s': cannot enable certificate generation, "
5059 "no CA certificate File configured at [%s:%d].\n",
5060 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005061 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005062 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005063
5064 /* read in the CA certificate */
5065 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005066 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5067 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005068 goto load_error;
5069 }
5070 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005071 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5072 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005073 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005074 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005075 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005076 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005077 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5078 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005079 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005080 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005081
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005082 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005083 bind_conf->ca_sign_cert = cacert;
5084 bind_conf->ca_sign_pkey = capkey;
5085 return err;
5086
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005087 read_error:
5088 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005089 if (capkey) EVP_PKEY_free(capkey);
5090 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005091 load_error:
5092 bind_conf->generate_certs = 0;
5093 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005094 return err;
5095}
5096
5097/* Release CA cert and private key used to generate certificated */
5098void
5099ssl_sock_free_ca(struct bind_conf *bind_conf)
5100{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005101 if (bind_conf->ca_sign_pkey)
5102 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5103 if (bind_conf->ca_sign_cert)
5104 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005105 bind_conf->ca_sign_pkey = NULL;
5106 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005107}
5108
Emeric Brun46591952012-05-18 15:47:34 +02005109/*
5110 * This function is called if SSL * context is not yet allocated. The function
5111 * is designed to be called before any other data-layer operation and sets the
5112 * handshake flag on the connection. It is safe to call it multiple times.
5113 * It returns 0 on success and -1 in error case.
5114 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005115static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005116{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005117 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005118 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005119 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005120 return 0;
5121
Willy Tarreau3c728722014-01-23 13:50:42 +01005122 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005123 return 0;
5124
Olivier Houchard66ab4982019-02-26 18:37:15 +01005125 ctx = pool_alloc(ssl_sock_ctx_pool);
5126 if (!ctx) {
5127 conn->err_code = CO_ER_SSL_NO_MEM;
5128 return -1;
5129 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005130 ctx->sent_early_data = 0;
5131 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005132 ctx->conn = conn;
5133
5134 /* Only work with sockets for now, this should be adapted when we'll
5135 * add QUIC support.
5136 */
5137 ctx->xprt = xprt_get(XPRT_RAW);
5138 if (ctx->xprt->init)
5139 ctx->xprt->init(conn, &ctx->xprt_ctx);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005140
Willy Tarreau20879a02012-12-03 16:32:10 +01005141 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5142 conn->err_code = CO_ER_SSL_TOO_MANY;
Willy Tarreau403edff2012-09-06 11:58:37 +02005143 return -1;
Willy Tarreau20879a02012-12-03 16:32:10 +01005144 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005145
Emeric Brun46591952012-05-18 15:47:34 +02005146 /* If it is in client mode initiate SSL session
5147 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005148 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005149 int may_retry = 1;
5150
5151 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005152 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005153 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5154 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005155 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005156 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005157 goto retry_connect;
5158 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005159 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005160 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005161 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005162 ctx->bio = BIO_new(ha_meth);
5163 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005164 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005165 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005166 goto retry_connect;
5167 }
Emeric Brun55476152014-11-12 17:35:37 +01005168 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005169 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005170 }
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005171#if HA_OPENSSL_VERSION_NUMBER < 0x10100000
Olivier Houcharda8955d52019-04-07 22:00:38 +02005172 ctx->bio->ptr = ctx;
5173#else
5174 BIO_set_data(ctx->bio, ctx);
5175#endif
5176 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005177
Evan Broderbe554312013-06-27 00:05:25 -07005178 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005179 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5180 SSL_free(ctx->ssl);
5181 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005182 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005183 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005184 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005185 goto retry_connect;
5186 }
Emeric Brun55476152014-11-12 17:35:37 +01005187 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005188 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005189 }
5190
Olivier Houchard66ab4982019-02-26 18:37:15 +01005191 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005192 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5193 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5194 SSL_SESSION *sess = d2i_SSL_SESSION(NULL, &ptr, __objt_server(conn->target)->ssl_ctx.reused_sess[tid].size);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005195 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005196 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005197 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5198 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005199 } else if (sess) {
5200 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005201 }
5202 }
Evan Broderbe554312013-06-27 00:05:25 -07005203
Emeric Brun46591952012-05-18 15:47:34 +02005204 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005205 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005206
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005207 _HA_ATOMIC_ADD(&sslconns, 1);
5208 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005209 *xprt_ctx = ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005210 return 0;
5211 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005212 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005213 int may_retry = 1;
5214
5215 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005216 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005217 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5218 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005219 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005220 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005221 goto retry_accept;
5222 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005223 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005224 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005225 }
Emeric Brun46591952012-05-18 15:47:34 +02005226
Olivier Houcharda8955d52019-04-07 22:00:38 +02005227 ctx->bio = BIO_new(ha_meth);
5228 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005229 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005230 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005231 goto retry_accept;
5232 }
Emeric Brun55476152014-11-12 17:35:37 +01005233 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005234 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005235 }
Willy Tarreau9a1ab082019-05-09 13:26:41 +02005236#if HA_OPENSSL_VERSION_NUMBER < 0x10100000
Olivier Houcharda8955d52019-04-07 22:00:38 +02005237 ctx->bio->ptr = ctx;
5238#else
5239 BIO_set_data(ctx->bio, ctx);
5240#endif
5241 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005242
Emeric Brune1f38db2012-09-03 20:36:47 +02005243 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005244 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5245 SSL_free(ctx->ssl);
5246 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005247 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005248 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005249 goto retry_accept;
5250 }
Emeric Brun55476152014-11-12 17:35:37 +01005251 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005252 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005253 }
5254
Olivier Houchard66ab4982019-02-26 18:37:15 +01005255 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005256
Emeric Brun46591952012-05-18 15:47:34 +02005257 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005258 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005259#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005260 conn->flags |= CO_FL_EARLY_SSL_HS;
5261#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005262
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005263 _HA_ATOMIC_ADD(&sslconns, 1);
5264 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005265 *xprt_ctx = ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005266 return 0;
5267 }
5268 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005269 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005270err:
5271 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005272 return -1;
5273}
5274
5275
5276/* This is the callback which is used when an SSL handshake is pending. It
5277 * updates the FD status if it wants some polling before being called again.
5278 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5279 * otherwise it returns non-zero and removes itself from the connection's
5280 * flags (the bit is provided in <flag> by the caller).
5281 */
5282int ssl_sock_handshake(struct connection *conn, unsigned int flag)
5283{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005284 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005285 int ret;
5286
Willy Tarreau3c728722014-01-23 13:50:42 +01005287 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005288 return 0;
5289
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005290 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005291 goto out_error;
5292
Willy Tarreau5db847a2019-05-09 14:13:35 +02005293#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005294 /*
5295 * Check if we have early data. If we do, we have to read them
5296 * before SSL_do_handshake() is called, And there's no way to
5297 * detect early data, except to try to read them
5298 */
5299 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5300 size_t read_data;
5301
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005302 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005303 1, &read_data);
5304 if (ret == SSL_READ_EARLY_DATA_ERROR)
5305 goto check_error;
5306 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5307 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5308 return 1;
5309 } else
5310 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5311 }
5312#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005313 /* If we use SSL_do_handshake to process a reneg initiated by
5314 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5315 * Usually SSL_write and SSL_read are used and process implicitly
5316 * the reneg handshake.
5317 * Here we use SSL_peek as a workaround for reneg.
5318 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005319 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005320 char c;
5321
Olivier Houchard66ab4982019-02-26 18:37:15 +01005322 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005323 if (ret <= 0) {
5324 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005325 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005326
Emeric Brun674b7432012-11-08 19:21:55 +01005327 if (ret == SSL_ERROR_WANT_WRITE) {
5328 /* SSL handshake needs to write, L4 connection may not be ready */
5329 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005330 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005331 fd_cant_send(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005332 return 0;
5333 }
5334 else if (ret == SSL_ERROR_WANT_READ) {
5335 /* handshake may have been completed but we have
5336 * no more data to read.
5337 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005338 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005339 ret = 1;
5340 goto reneg_ok;
5341 }
5342 /* SSL handshake needs to read, L4 connection is ready */
5343 if (conn->flags & CO_FL_WAIT_L4_CONN)
5344 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5345 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005346 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005347 fd_cant_recv(conn->handle.fd);
Emeric Brun674b7432012-11-08 19:21:55 +01005348 return 0;
5349 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005350#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005351 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005352 ssl_async_process_fds(conn, ctx->ssl);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005353 return 0;
5354 }
5355#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005356 else if (ret == SSL_ERROR_SYSCALL) {
5357 /* if errno is null, then connection was successfully established */
5358 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5359 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005360 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005361#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005362 conn->err_code = CO_ER_SSL_HANDSHAKE;
5363#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005364 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005365#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005366 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005367 empty_handshake = state == TLS_ST_BEFORE;
5368#else
Ilya Shipitsin54832b92019-05-05 23:27:54 +05005369 empty_handshake = SSL_state((SSL *)ctx->ssl) == SSL_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005370#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005371 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005372 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005373 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005374 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5375 else
5376 conn->err_code = CO_ER_SSL_EMPTY;
5377 }
5378 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005379 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005380 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5381 else
5382 conn->err_code = CO_ER_SSL_ABORT;
5383 }
5384 }
5385 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005386 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005387 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005388 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005389 conn->err_code = CO_ER_SSL_HANDSHAKE;
5390 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005391#endif
Willy Tarreau20879a02012-12-03 16:32:10 +01005392 }
Emeric Brun674b7432012-11-08 19:21:55 +01005393 goto out_error;
5394 }
5395 else {
5396 /* Fail on all other handshake errors */
5397 /* Note: OpenSSL may leave unread bytes in the socket's
5398 * buffer, causing an RST to be emitted upon close() on
5399 * TCP sockets. We first try to drain possibly pending
5400 * data to avoid this as much as possible.
5401 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005402 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005403 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005404 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005405 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005406 goto out_error;
5407 }
5408 }
5409 /* read some data: consider handshake completed */
5410 goto reneg_ok;
5411 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005412 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005413check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005414 if (ret != 1) {
5415 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005416 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005417
5418 if (ret == SSL_ERROR_WANT_WRITE) {
5419 /* SSL handshake needs to write, L4 connection may not be ready */
5420 __conn_sock_stop_recv(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005421 __conn_sock_want_send(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005422 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005423 return 0;
5424 }
5425 else if (ret == SSL_ERROR_WANT_READ) {
5426 /* SSL handshake needs to read, L4 connection is ready */
5427 if (conn->flags & CO_FL_WAIT_L4_CONN)
5428 conn->flags &= ~CO_FL_WAIT_L4_CONN;
5429 __conn_sock_stop_send(conn);
Willy Tarreaue1f50c42014-01-22 20:02:06 +01005430 __conn_sock_want_recv(conn);
Willy Tarreau585744b2017-08-24 14:31:19 +02005431 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005432 return 0;
5433 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005434#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005435 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005436 ssl_async_process_fds(conn, ctx->ssl);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005437 return 0;
5438 }
5439#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005440 else if (ret == SSL_ERROR_SYSCALL) {
5441 /* if errno is null, then connection was successfully established */
5442 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5443 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005444 if (!conn->err_code) {
Emeric Brun77e89192018-08-16 11:36:40 +02005445#ifdef OPENSSL_IS_BORINGSSL /* BoringSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005446 conn->err_code = CO_ER_SSL_HANDSHAKE;
5447#else
5448 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005449#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005450 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005451 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005452#else
Ilya Shipitsin54832b92019-05-05 23:27:54 +05005453 empty_handshake = SSL_state((SSL *)ctx->ssl) == SSL_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005454#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005455 if (empty_handshake) {
5456 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005457 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005458 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5459 else
5460 conn->err_code = CO_ER_SSL_EMPTY;
5461 }
5462 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005463 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005464 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5465 else
5466 conn->err_code = CO_ER_SSL_ABORT;
5467 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005468 }
5469 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005470 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005471 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5472 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005473 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005474 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005475#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02005476 }
Willy Tarreau89230192012-09-28 20:22:13 +02005477 goto out_error;
5478 }
Emeric Brun46591952012-05-18 15:47:34 +02005479 else {
5480 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005481 /* Note: OpenSSL may leave unread bytes in the socket's
5482 * buffer, causing an RST to be emitted upon close() on
5483 * TCP sockets. We first try to drain possibly pending
5484 * data to avoid this as much as possible.
5485 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005486 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005487 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005488 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005489 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005490 goto out_error;
5491 }
5492 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005493#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005494 else {
5495 /*
5496 * If the server refused the early data, we have to send a
5497 * 425 to the client, as we no longer have the data to sent
5498 * them again.
5499 */
5500 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005501 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005502 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5503 goto out_error;
5504 }
5505 }
5506 }
5507#endif
5508
Emeric Brun46591952012-05-18 15:47:34 +02005509
Emeric Brun674b7432012-11-08 19:21:55 +01005510reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005511
Willy Tarreau5db847a2019-05-09 14:13:35 +02005512#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005513 /* ASYNC engine API doesn't support moving read/write
5514 * buffers. So we disable ASYNC mode right after
5515 * the handshake to avoid buffer oveflows.
5516 */
5517 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005518 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005519#endif
Emeric Brun46591952012-05-18 15:47:34 +02005520 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005521 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005522 if (objt_server(conn->target)) {
5523 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5524 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5525 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005526 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005527 else {
5528 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5529 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5530 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5531 }
Emeric Brun46591952012-05-18 15:47:34 +02005532 }
5533
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005534#ifdef OPENSSL_IS_BORINGSSL
Olivier Houchard66ab4982019-02-26 18:37:15 +01005535 if ((conn->flags & CO_FL_EARLY_SSL_HS) && !SSL_in_early_data(ctx->ssl))
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005536 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5537#endif
Emeric Brun46591952012-05-18 15:47:34 +02005538 /* The connection is now established at both layers, it's time to leave */
5539 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5540 return 1;
5541
5542 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005543 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005544 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005545 ERR_clear_error();
5546
Emeric Brun9fa89732012-10-04 17:09:56 +02005547 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005548 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5549 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5550 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005551 }
5552
Emeric Brun46591952012-05-18 15:47:34 +02005553 /* Fail on all other handshake errors */
5554 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005555 if (!conn->err_code)
5556 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005557 return 0;
5558}
5559
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005560static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005561{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005562
5563 return conn_subscribe(conn, NULL, event_type, param);
Olivier Houcharddf357842019-03-21 16:30:07 +01005564}
5565
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005566static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005567{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005568
5569 return conn_unsubscribe(conn, NULL, event_type, param);
Olivier Houcharddf357842019-03-21 16:30:07 +01005570}
5571
Emeric Brun46591952012-05-18 15:47:34 +02005572/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005573 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005574 * buffer wraps, in which case a second call may be performed. The connection's
5575 * flags are updated with whatever special event is detected (error, read0,
5576 * empty). The caller is responsible for taking care of those events and
5577 * avoiding the call if inappropriate. The function does not call the
5578 * connection's polling update function, so the caller is responsible for this.
5579 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005580static size_t ssl_sock_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005581{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005582 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005583 ssize_t ret;
5584 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005585
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005586 conn_refresh_polling_flags(conn);
5587
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005588 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005589 goto out_error;
5590
5591 if (conn->flags & CO_FL_HANDSHAKE)
5592 /* a handshake was requested */
5593 return 0;
5594
Emeric Brun46591952012-05-18 15:47:34 +02005595 /* read the largest possible block. For this, we perform only one call
5596 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5597 * in which case we accept to do it once again. A new attempt is made on
5598 * EINTR too.
5599 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005600 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005601 int need_out = 0;
5602
Willy Tarreau591d4452018-06-15 17:21:00 +02005603 try = b_contig_space(buf);
5604 if (!try)
5605 break;
5606
Willy Tarreauabf08d92014-01-14 11:31:27 +01005607 if (try > count)
5608 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005609
Olivier Houchardc2aae742017-09-22 18:26:28 +02005610 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005611 ctx->tmp_early_data != -1) {
5612 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005613 done++;
5614 try--;
5615 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005616 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005617 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005618 continue;
5619 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005620
Willy Tarreau5db847a2019-05-09 14:13:35 +02005621#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005622 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5623 size_t read_length;
5624
Olivier Houchard66ab4982019-02-26 18:37:15 +01005625 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005626 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005627 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5628 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005629 conn->flags |= CO_FL_EARLY_DATA;
5630 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5631 ret == SSL_READ_EARLY_DATA_FINISH) {
5632 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5633 /*
5634 * We're done reading the early data,
5635 * let's make the handshake
5636 */
5637 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5638 conn->flags |= CO_FL_SSL_WAIT_HS;
5639 need_out = 1;
5640 if (read_length == 0)
5641 break;
5642 }
5643 ret = read_length;
5644 }
5645 } else
5646#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01005647 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005648#ifdef OPENSSL_IS_BORINGSSL
5649 if (conn->flags & CO_FL_EARLY_SSL_HS) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005650 if (SSL_in_early_data(ctx->ssl)) {
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005651 if (ret > 0)
5652 conn->flags |= CO_FL_EARLY_DATA;
5653 } else {
Emmanuel Hocdetcebd7962017-11-27 16:14:40 +01005654 conn->flags &= ~(CO_FL_EARLY_SSL_HS);
Emmanuel Hocdetca6a9572017-11-23 12:40:07 +01005655 }
5656 }
5657#endif
Emeric Brune1f38db2012-09-03 20:36:47 +02005658 if (conn->flags & CO_FL_ERROR) {
5659 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005660 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005661 }
Emeric Brun46591952012-05-18 15:47:34 +02005662 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005663 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005664 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005665 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005666 }
Emeric Brun46591952012-05-18 15:47:34 +02005667 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005668 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005669 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005670 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005671 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005672 __conn_sock_want_send(conn);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005673#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005674 /* Async mode can be re-enabled, because we're leaving data state.*/
5675 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005676 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005677#endif
Emeric Brun46591952012-05-18 15:47:34 +02005678 break;
5679 }
5680 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005681 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005682 /* handshake is running, and it may need to re-enable read */
5683 conn->flags |= CO_FL_SSL_WAIT_HS;
5684 __conn_sock_want_recv(conn);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005685#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005686 /* Async mode can be re-enabled, because we're leaving data state.*/
5687 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005688 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005689#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005690 break;
5691 }
Emeric Brun46591952012-05-18 15:47:34 +02005692 /* we need to poll for retry a read later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005693 fd_cant_recv(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005694 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005695 } else if (ret == SSL_ERROR_ZERO_RETURN)
5696 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005697 /* For SSL_ERROR_SYSCALL, make sure to clear the error
5698 * stack before shutting down the connection for
5699 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005700 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
5701 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02005702 /* otherwise it's a real error */
5703 goto out_error;
5704 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005705 if (need_out)
5706 break;
Emeric Brun46591952012-05-18 15:47:34 +02005707 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005708 leave:
5709 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005710 return done;
5711
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005712 clear_ssl_error:
5713 /* Clear openssl global errors stack */
5714 ssl_sock_dump_errors(conn);
5715 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02005716 read0:
5717 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005718 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01005719
Emeric Brun46591952012-05-18 15:47:34 +02005720 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01005721 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01005722 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005723 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005724 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005725 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005726}
5727
5728
Willy Tarreau787db9a2018-06-14 18:31:46 +02005729/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
5730 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
5731 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02005732 * Only one call to send() is performed, unless the buffer wraps, in which case
5733 * a second call may be performed. The connection's flags are updated with
5734 * whatever special event is detected (error, empty). The caller is responsible
5735 * for taking care of those events and avoiding the call if inappropriate. The
5736 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02005737 * is responsible for this. The buffer's output is not adjusted, it's up to the
5738 * caller to take care of this. It's up to the caller to update the buffer's
5739 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02005740 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005741static size_t ssl_sock_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, int flags)
Emeric Brun46591952012-05-18 15:47:34 +02005742{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005743 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005744 ssize_t ret;
5745 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02005746
5747 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005748 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005749
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005750 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005751 goto out_error;
5752
Olivier Houchard010941f2019-05-03 20:56:19 +02005753 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02005754 /* a handshake was requested */
5755 return 0;
5756
5757 /* send the largest possible block. For this we perform only one call
5758 * to send() unless the buffer wraps and we exactly fill the first hunk,
5759 * in which case we accept to do it once again.
5760 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02005761 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02005762#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005763 size_t written_data;
5764#endif
5765
Willy Tarreau787db9a2018-06-14 18:31:46 +02005766 try = b_contig_data(buf, done);
5767 if (try > count)
5768 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01005769
Willy Tarreau7bed9452014-02-02 02:00:24 +01005770 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005771 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01005772 global_ssl.max_record && try > global_ssl.max_record) {
5773 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005774 }
5775 else {
5776 /* we need to keep the information about the fact that
5777 * we're not limiting the upcoming send(), because if it
5778 * fails, we'll have to retry with at least as many data.
5779 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005780 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01005781 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01005782
Willy Tarreau5db847a2019-05-09 14:13:35 +02005783#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02005784 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005785 unsigned int max_early;
5786
Olivier Houchard522eea72017-11-03 16:27:47 +01005787 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01005788 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01005789 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005790 if (SSL_get0_session(ctx->ssl))
5791 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01005792 else
5793 max_early = 0;
5794 }
5795
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005796 if (try + ctx->sent_early_data > max_early) {
5797 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01005798 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02005799 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005800 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01005801 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02005802 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005803 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005804 if (ret == 1) {
5805 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005806 ctx->sent_early_data += ret;
Olivier Houchard010941f2019-05-03 20:56:19 +02005807 if (objt_server(conn->target))
Olivier Houchard522eea72017-11-03 16:27:47 +01005808 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard522eea72017-11-03 16:27:47 +01005809
Olivier Houchardc2aae742017-09-22 18:26:28 +02005810 }
5811
5812 } else
5813#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01005814 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01005815
Emeric Brune1f38db2012-09-03 20:36:47 +02005816 if (conn->flags & CO_FL_ERROR) {
5817 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005818 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005819 }
Emeric Brun46591952012-05-18 15:47:34 +02005820 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01005821 /* A send succeeded, so we can consier ourself connected */
5822 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005823 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02005824 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005825 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005826 }
5827 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005828 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005829
Emeric Brun46591952012-05-18 15:47:34 +02005830 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005831 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01005832 /* handshake is running, and it may need to re-enable write */
5833 conn->flags |= CO_FL_SSL_WAIT_HS;
5834 __conn_sock_want_send(conn);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005835#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005836 /* Async mode can be re-enabled, because we're leaving data state.*/
5837 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005838 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005839#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01005840 break;
5841 }
Emeric Brun46591952012-05-18 15:47:34 +02005842 /* we need to poll to retry a write later */
Willy Tarreau585744b2017-08-24 14:31:19 +02005843 fd_cant_send(conn->handle.fd);
Emeric Brun46591952012-05-18 15:47:34 +02005844 break;
5845 }
5846 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005847 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02005848 conn->flags |= CO_FL_SSL_WAIT_HS;
Emeric Brun8af8dd12012-11-08 17:56:20 +01005849 __conn_sock_want_recv(conn);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005850#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005851 /* Async mode can be re-enabled, because we're leaving data state.*/
5852 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005853 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005854#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005855 break;
5856 }
Emeric Brun46591952012-05-18 15:47:34 +02005857 goto out_error;
5858 }
5859 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005860 leave:
5861 conn_cond_update_sock_polling(conn);
Emeric Brun46591952012-05-18 15:47:34 +02005862 return done;
5863
5864 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005865 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005866 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005867 ERR_clear_error();
5868
Emeric Brun46591952012-05-18 15:47:34 +02005869 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005870 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02005871}
5872
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005873static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02005874
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005875 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005876
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005877 if (ctx) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02005878#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02005879 if (global_ssl.async) {
5880 OSSL_ASYNC_FD all_fd[32], afd;
5881 size_t num_all_fds = 0;
5882 int i;
5883
Olivier Houchard66ab4982019-02-26 18:37:15 +01005884 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02005885 if (num_all_fds > 32) {
5886 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
5887 return;
5888 }
5889
Olivier Houchard66ab4982019-02-26 18:37:15 +01005890 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02005891
5892 /* If an async job is pending, we must try to
5893 to catch the end using polling before calling
5894 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005895 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02005896 for (i=0 ; i < num_all_fds ; i++) {
5897 /* switch on an handler designed to
5898 * handle the SSL_free
5899 */
5900 afd = all_fd[i];
5901 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005902 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02005903 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00005904 /* To ensure that the fd cache won't be used
5905 * and we'll catch a real RD event.
5906 */
5907 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02005908 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005909 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005910 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005911 return;
5912 }
Emeric Brun3854e012017-05-17 20:42:48 +02005913 /* Else we can remove the fds from the fdtab
5914 * and call SSL_free.
5915 * note: we do a fd_remove and not a delete
5916 * because the fd is owned by the engine.
5917 * the engine is responsible to close
5918 */
5919 for (i=0 ; i < num_all_fds ; i++)
5920 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005921 }
5922#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01005923 SSL_free(ctx->ssl);
5924 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005925 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005926 }
Emeric Brun46591952012-05-18 15:47:34 +02005927}
5928
5929/* This function tries to perform a clean shutdown on an SSL connection, and in
5930 * any case, flags the connection as reusable if no handshake was in progress.
5931 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005932static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02005933{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005934 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005935
Emeric Brun46591952012-05-18 15:47:34 +02005936 if (conn->flags & CO_FL_HANDSHAKE)
5937 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01005938 if (!clean)
5939 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005940 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02005941 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005942 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01005943 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005944 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005945 ERR_clear_error();
5946 }
Emeric Brun46591952012-05-18 15:47:34 +02005947}
5948
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005949/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02005950int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005951{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005952 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005953 struct pkey_info *pkinfo;
5954 int bits = 0;
5955 int sig = TLSEXT_signature_anonymous;
5956 int len = -1;
5957
5958 if (!ssl_sock_is_ssl(conn))
5959 return 0;
5960
Olivier Houchard66ab4982019-02-26 18:37:15 +01005961 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005962 if (pkinfo) {
5963 sig = pkinfo->sig;
5964 bits = pkinfo->bits;
5965 } else {
5966 /* multicert and generated cert have no pkey info */
5967 X509 *crt;
5968 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005969 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01005970 if (!crt)
5971 return 0;
5972 pkey = X509_get_pubkey(crt);
5973 if (pkey) {
5974 bits = EVP_PKEY_bits(pkey);
5975 switch(EVP_PKEY_base_id(pkey)) {
5976 case EVP_PKEY_RSA:
5977 sig = TLSEXT_signature_rsa;
5978 break;
5979 case EVP_PKEY_EC:
5980 sig = TLSEXT_signature_ecdsa;
5981 break;
5982 case EVP_PKEY_DSA:
5983 sig = TLSEXT_signature_dsa;
5984 break;
5985 }
5986 EVP_PKEY_free(pkey);
5987 }
5988 }
5989
5990 switch(sig) {
5991 case TLSEXT_signature_rsa:
5992 len = chunk_printf(out, "RSA%d", bits);
5993 break;
5994 case TLSEXT_signature_ecdsa:
5995 len = chunk_printf(out, "EC%d", bits);
5996 break;
5997 case TLSEXT_signature_dsa:
5998 len = chunk_printf(out, "DSA%d", bits);
5999 break;
6000 default:
6001 return 0;
6002 }
6003 if (len < 0)
6004 return 0;
6005 return 1;
6006}
6007
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006008/* used for ppv2 cert signature (can be used for logging) */
6009const char *ssl_sock_get_cert_sig(struct connection *conn)
6010{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006011 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6012
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006013 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6014 X509 *crt;
6015
6016 if (!ssl_sock_is_ssl(conn))
6017 return NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006018 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006019 if (!crt)
6020 return NULL;
6021 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6022 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6023}
6024
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006025/* used for ppv2 authority */
6026const char *ssl_sock_get_sni(struct connection *conn)
6027{
6028#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Olivier Houchard66ab4982019-02-26 18:37:15 +01006029 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6030
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006031 if (!ssl_sock_is_ssl(conn))
6032 return NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006033 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006034#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006035 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006036#endif
6037}
6038
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006039/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006040const char *ssl_sock_get_cipher_name(struct connection *conn)
6041{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006042 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6043
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006044 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006045 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006046
Olivier Houchard66ab4982019-02-26 18:37:15 +01006047 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006048}
6049
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006050/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006051const char *ssl_sock_get_proto_version(struct connection *conn)
6052{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006053 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6054
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006055 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006056 return NULL;
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006057
Olivier Houchard66ab4982019-02-26 18:37:15 +01006058 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006059}
6060
Willy Tarreau8d598402012-10-22 17:58:39 +02006061/* Extract a serial from a cert, and copy it to a chunk.
6062 * Returns 1 if serial is found and copied, 0 if no serial found and
6063 * -1 if output is not large enough.
6064 */
6065static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006066ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006067{
6068 ASN1_INTEGER *serial;
6069
6070 serial = X509_get_serialNumber(crt);
6071 if (!serial)
6072 return 0;
6073
6074 if (out->size < serial->length)
6075 return -1;
6076
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006077 memcpy(out->area, serial->data, serial->length);
6078 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006079 return 1;
6080}
6081
Emeric Brun43e79582014-10-29 19:03:26 +01006082/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006083 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6084 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006085 */
6086static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006087ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006088{
6089 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006090 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006091
6092 len =i2d_X509(crt, NULL);
6093 if (len <= 0)
6094 return 1;
6095
6096 if (out->size < len)
6097 return -1;
6098
6099 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006100 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006101 return 1;
6102}
6103
Emeric Brunce5ad802012-10-22 14:11:22 +02006104
Willy Tarreau83061a82018-07-13 11:56:34 +02006105/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006106 * Returns 1 if serial is found and copied, 0 if no valid time found
6107 * and -1 if output is not large enough.
6108 */
6109static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006110ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006111{
6112 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6113 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6114
6115 if (gentm->length < 12)
6116 return 0;
6117 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6118 return 0;
6119 if (out->size < gentm->length-2)
6120 return -1;
6121
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006122 memcpy(out->area, gentm->data+2, gentm->length-2);
6123 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006124 return 1;
6125 }
6126 else if (tm->type == V_ASN1_UTCTIME) {
6127 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6128
6129 if (utctm->length < 10)
6130 return 0;
6131 if (utctm->data[0] >= 0x35)
6132 return 0;
6133 if (out->size < utctm->length)
6134 return -1;
6135
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006136 memcpy(out->area, utctm->data, utctm->length);
6137 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006138 return 1;
6139 }
6140
6141 return 0;
6142}
6143
Emeric Brun87855892012-10-17 17:39:35 +02006144/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6145 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6146 */
6147static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006148ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6149 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006150{
6151 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006152 ASN1_OBJECT *obj;
6153 ASN1_STRING *data;
6154 const unsigned char *data_ptr;
6155 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006156 int i, j, n;
6157 int cur = 0;
6158 const char *s;
6159 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006160 int name_count;
6161
6162 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006163
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006164 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006165 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006166 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006167 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006168 else
6169 j = i;
6170
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006171 ne = X509_NAME_get_entry(a, j);
6172 obj = X509_NAME_ENTRY_get_object(ne);
6173 data = X509_NAME_ENTRY_get_data(ne);
6174 data_ptr = ASN1_STRING_get0_data(data);
6175 data_len = ASN1_STRING_length(data);
6176 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006177 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006178 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006179 s = tmp;
6180 }
6181
6182 if (chunk_strcasecmp(entry, s) != 0)
6183 continue;
6184
6185 if (pos < 0)
6186 cur--;
6187 else
6188 cur++;
6189
6190 if (cur != pos)
6191 continue;
6192
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006193 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006194 return -1;
6195
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006196 memcpy(out->area, data_ptr, data_len);
6197 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006198 return 1;
6199 }
6200
6201 return 0;
6202
6203}
6204
6205/* Extract and format full DN from a X509_NAME and copy result into a chunk
6206 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6207 */
6208static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006209ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006210{
6211 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006212 ASN1_OBJECT *obj;
6213 ASN1_STRING *data;
6214 const unsigned char *data_ptr;
6215 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006216 int i, n, ln;
6217 int l = 0;
6218 const char *s;
6219 char *p;
6220 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006221 int name_count;
6222
6223
6224 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006225
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006226 out->data = 0;
6227 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006228 for (i = 0; i < name_count; i++) {
6229 ne = X509_NAME_get_entry(a, i);
6230 obj = X509_NAME_ENTRY_get_object(ne);
6231 data = X509_NAME_ENTRY_get_data(ne);
6232 data_ptr = ASN1_STRING_get0_data(data);
6233 data_len = ASN1_STRING_length(data);
6234 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006235 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006236 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006237 s = tmp;
6238 }
6239 ln = strlen(s);
6240
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006241 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006242 if (l > out->size)
6243 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006244 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006245
6246 *(p++)='/';
6247 memcpy(p, s, ln);
6248 p += ln;
6249 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006250 memcpy(p, data_ptr, data_len);
6251 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006252 }
6253
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006254 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006255 return 0;
6256
6257 return 1;
6258}
6259
Olivier Houchardab28a322018-12-21 19:45:40 +01006260void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6261{
6262#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006263 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6264
6265 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006266#endif
6267}
6268
Willy Tarreau119a4082016-12-22 21:58:38 +01006269/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6270 * to disable SNI.
6271 */
Willy Tarreau63076412015-07-10 11:33:32 +02006272void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6273{
6274#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Olivier Houchard66ab4982019-02-26 18:37:15 +01006275 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6276
Willy Tarreau119a4082016-12-22 21:58:38 +01006277 char *prev_name;
6278
Willy Tarreau63076412015-07-10 11:33:32 +02006279 if (!ssl_sock_is_ssl(conn))
6280 return;
6281
Willy Tarreau119a4082016-12-22 21:58:38 +01006282 /* if the SNI changes, we must destroy the reusable context so that a
6283 * new connection will present a new SNI. As an optimization we could
6284 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6285 * server.
6286 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006287 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006288 if ((!prev_name && hostname) ||
6289 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006290 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006291
Olivier Houchard66ab4982019-02-26 18:37:15 +01006292 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006293#endif
6294}
6295
Emeric Brun0abf8362014-06-24 18:26:41 +02006296/* Extract peer certificate's common name into the chunk dest
6297 * Returns
6298 * the len of the extracted common name
6299 * or 0 if no CN found in DN
6300 * or -1 on error case (i.e. no peer certificate)
6301 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006302int ssl_sock_get_remote_common_name(struct connection *conn,
6303 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006304{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006305 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006306 X509 *crt = NULL;
6307 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006308 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006309 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006310 .area = (char *)&find_cn,
6311 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006312 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006313 int result = -1;
David Safb76832014-05-08 23:42:08 -04006314
6315 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006316 goto out;
David Safb76832014-05-08 23:42:08 -04006317
6318 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006319 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006320 if (!crt)
6321 goto out;
6322
6323 name = X509_get_subject_name(crt);
6324 if (!name)
6325 goto out;
David Safb76832014-05-08 23:42:08 -04006326
Emeric Brun0abf8362014-06-24 18:26:41 +02006327 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6328out:
David Safb76832014-05-08 23:42:08 -04006329 if (crt)
6330 X509_free(crt);
6331
6332 return result;
6333}
6334
Dave McCowan328fb582014-07-30 10:39:13 -04006335/* returns 1 if client passed a certificate for this session, 0 if not */
6336int ssl_sock_get_cert_used_sess(struct connection *conn)
6337{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006338 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006339 X509 *crt = NULL;
6340
6341 if (!ssl_sock_is_ssl(conn))
6342 return 0;
6343
6344 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006345 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006346 if (!crt)
6347 return 0;
6348
6349 X509_free(crt);
6350 return 1;
6351}
6352
6353/* returns 1 if client passed a certificate for this connection, 0 if not */
6354int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006355{
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006356 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6357
David Safb76832014-05-08 23:42:08 -04006358 if (!ssl_sock_is_ssl(conn))
6359 return 0;
6360
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006361 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006362}
6363
6364/* returns result from SSL verify */
6365unsigned int ssl_sock_get_verify_result(struct connection *conn)
6366{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006367 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6368
David Safb76832014-05-08 23:42:08 -04006369 if (!ssl_sock_is_ssl(conn))
6370 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
6371
Olivier Houchard66ab4982019-02-26 18:37:15 +01006372 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006373}
6374
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006375/* Returns the application layer protocol name in <str> and <len> when known.
6376 * Zero is returned if the protocol name was not found, otherwise non-zero is
6377 * returned. The string is allocated in the SSL context and doesn't have to be
6378 * freed by the caller. NPN is also checked if available since older versions
6379 * of openssl (1.0.1) which are more common in field only support this one.
6380 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006381static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006382{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006383#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6384 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006385 struct ssl_sock_ctx *ctx = xprt_ctx;
6386 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006387 return 0;
6388
6389 *str = NULL;
6390
6391#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006392 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006393 if (*str)
6394 return 1;
6395#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006396#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006397 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006398 if (*str)
6399 return 1;
6400#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006401#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006402 return 0;
6403}
6404
Willy Tarreau7875d092012-09-10 08:20:03 +02006405/***** Below are some sample fetching functions for ACL/patterns *****/
6406
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006407static int
6408smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6409{
6410 struct connection *conn;
6411
6412 conn = objt_conn(smp->sess->origin);
6413 if (!conn || conn->xprt != &ssl_sock)
6414 return 0;
6415
6416 smp->flags = 0;
6417 smp->data.type = SMP_T_BOOL;
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006418 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6419 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006420
6421 return 1;
6422}
6423
Emeric Brune64aef12012-09-21 13:15:06 +02006424/* boolean, returns true if client cert was present */
6425static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006426smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006427{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006428 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006429 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006430
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006431 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006432 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006433 return 0;
6434
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006435 ctx = conn->xprt_ctx;
6436
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006437 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006438 smp->flags |= SMP_F_MAY_CHANGE;
6439 return 0;
6440 }
6441
6442 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006443 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006444 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006445
6446 return 1;
6447}
6448
Emeric Brun43e79582014-10-29 19:03:26 +01006449/* binary, returns a certificate in a binary chunk (der/raw).
6450 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6451 * should be use.
6452 */
6453static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006454smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006455{
6456 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6457 X509 *crt = NULL;
6458 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006459 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006460 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006461 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006462
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006463 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006464 if (!conn || conn->xprt != &ssl_sock)
6465 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006466 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006467
6468 if (!(conn->flags & CO_FL_CONNECTED)) {
6469 smp->flags |= SMP_F_MAY_CHANGE;
6470 return 0;
6471 }
6472
6473 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006474 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006475 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006476 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006477
6478 if (!crt)
6479 goto out;
6480
6481 smp_trash = get_trash_chunk();
6482 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6483 goto out;
6484
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006485 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006486 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006487 ret = 1;
6488out:
6489 /* SSL_get_peer_certificate, it increase X509 * ref count */
6490 if (cert_peer && crt)
6491 X509_free(crt);
6492 return ret;
6493}
6494
Emeric Brunba841a12014-04-30 17:05:08 +02006495/* binary, returns serial of certificate in a binary chunk.
6496 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6497 * should be use.
6498 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006499static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006500smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006501{
Emeric Brunba841a12014-04-30 17:05:08 +02006502 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006503 X509 *crt = NULL;
6504 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006505 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006506 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006507 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006508
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006509 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006510 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006511 return 0;
6512
Olivier Houchard66ab4982019-02-26 18:37:15 +01006513 ctx = conn->xprt_ctx;
6514
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006515 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006516 smp->flags |= SMP_F_MAY_CHANGE;
6517 return 0;
6518 }
6519
Emeric Brunba841a12014-04-30 17:05:08 +02006520 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006521 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006522 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006523 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006524
Willy Tarreau8d598402012-10-22 17:58:39 +02006525 if (!crt)
6526 goto out;
6527
Willy Tarreau47ca5452012-12-23 20:22:19 +01006528 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006529 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6530 goto out;
6531
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006532 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006533 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006534 ret = 1;
6535out:
Emeric Brunba841a12014-04-30 17:05:08 +02006536 /* SSL_get_peer_certificate, it increase X509 * ref count */
6537 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006538 X509_free(crt);
6539 return ret;
6540}
Emeric Brune64aef12012-09-21 13:15:06 +02006541
Emeric Brunba841a12014-04-30 17:05:08 +02006542/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6543 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6544 * should be use.
6545 */
James Votha051b4a2013-05-14 20:37:59 +02006546static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006547smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006548{
Emeric Brunba841a12014-04-30 17:05:08 +02006549 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006550 X509 *crt = NULL;
6551 const EVP_MD *digest;
6552 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006553 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006554 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006555 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006556
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006557 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006558 if (!conn || conn->xprt != &ssl_sock)
6559 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006560 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006561
6562 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006563 smp->flags |= SMP_F_MAY_CHANGE;
6564 return 0;
6565 }
6566
Emeric Brunba841a12014-04-30 17:05:08 +02006567 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006568 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006569 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006570 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006571 if (!crt)
6572 goto out;
6573
6574 smp_trash = get_trash_chunk();
6575 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006576 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6577 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006578
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006579 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006580 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006581 ret = 1;
6582out:
Emeric Brunba841a12014-04-30 17:05:08 +02006583 /* SSL_get_peer_certificate, it increase X509 * ref count */
6584 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006585 X509_free(crt);
6586 return ret;
6587}
6588
Emeric Brunba841a12014-04-30 17:05:08 +02006589/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6590 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6591 * should be use.
6592 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006593static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006594smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006595{
Emeric Brunba841a12014-04-30 17:05:08 +02006596 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006597 X509 *crt = NULL;
6598 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006599 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006600 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006601 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006602
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006603 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006604 if (!conn || conn->xprt != &ssl_sock)
6605 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006606 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006607
6608 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006609 smp->flags |= SMP_F_MAY_CHANGE;
6610 return 0;
6611 }
6612
Emeric Brunba841a12014-04-30 17:05:08 +02006613 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006614 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006615 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006616 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006617 if (!crt)
6618 goto out;
6619
Willy Tarreau47ca5452012-12-23 20:22:19 +01006620 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006621 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006622 goto out;
6623
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006624 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006625 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006626 ret = 1;
6627out:
Emeric Brunba841a12014-04-30 17:05:08 +02006628 /* SSL_get_peer_certificate, it increase X509 * ref count */
6629 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006630 X509_free(crt);
6631 return ret;
6632}
6633
Emeric Brunba841a12014-04-30 17:05:08 +02006634/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6635 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6636 * should be use.
6637 */
Emeric Brun87855892012-10-17 17:39:35 +02006638static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006639smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006640{
Emeric Brunba841a12014-04-30 17:05:08 +02006641 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006642 X509 *crt = NULL;
6643 X509_NAME *name;
6644 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006645 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006646 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006647 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006648
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006649 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006650 if (!conn || conn->xprt != &ssl_sock)
6651 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006652 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006653
6654 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006655 smp->flags |= SMP_F_MAY_CHANGE;
6656 return 0;
6657 }
6658
Emeric Brunba841a12014-04-30 17:05:08 +02006659 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006660 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006661 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006662 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006663 if (!crt)
6664 goto out;
6665
6666 name = X509_get_issuer_name(crt);
6667 if (!name)
6668 goto out;
6669
Willy Tarreau47ca5452012-12-23 20:22:19 +01006670 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006671 if (args && args[0].type == ARGT_STR) {
6672 int pos = 1;
6673
6674 if (args[1].type == ARGT_SINT)
6675 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006676
6677 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6678 goto out;
6679 }
6680 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6681 goto out;
6682
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006683 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006684 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006685 ret = 1;
6686out:
Emeric Brunba841a12014-04-30 17:05:08 +02006687 /* SSL_get_peer_certificate, it increase X509 * ref count */
6688 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006689 X509_free(crt);
6690 return ret;
6691}
6692
Emeric Brunba841a12014-04-30 17:05:08 +02006693/* string, returns notbefore date in ASN1_UTCTIME format.
6694 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6695 * should be use.
6696 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006697static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006698smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006699{
Emeric Brunba841a12014-04-30 17:05:08 +02006700 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006701 X509 *crt = NULL;
6702 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006703 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006704 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006705 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006706
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006707 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006708 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02006709 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006710 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006711
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006712 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006713 smp->flags |= SMP_F_MAY_CHANGE;
6714 return 0;
6715 }
6716
Emeric Brunba841a12014-04-30 17:05:08 +02006717 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006718 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006719 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006720 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006721 if (!crt)
6722 goto out;
6723
Willy Tarreau47ca5452012-12-23 20:22:19 +01006724 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006725 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006726 goto out;
6727
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006728 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006729 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006730 ret = 1;
6731out:
Emeric Brunba841a12014-04-30 17:05:08 +02006732 /* SSL_get_peer_certificate, it increase X509 * ref count */
6733 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006734 X509_free(crt);
6735 return ret;
6736}
6737
Emeric Brunba841a12014-04-30 17:05:08 +02006738/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
6739 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6740 * should be use.
6741 */
Emeric Brun87855892012-10-17 17:39:35 +02006742static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006743smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006744{
Emeric Brunba841a12014-04-30 17:05:08 +02006745 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006746 X509 *crt = NULL;
6747 X509_NAME *name;
6748 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006749 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006750 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006751 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02006752
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006753 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006754 if (!conn || conn->xprt != &ssl_sock)
6755 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006756 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006757
6758 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02006759 smp->flags |= SMP_F_MAY_CHANGE;
6760 return 0;
6761 }
6762
Emeric Brunba841a12014-04-30 17:05:08 +02006763 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006764 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006765 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006766 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02006767 if (!crt)
6768 goto out;
6769
6770 name = X509_get_subject_name(crt);
6771 if (!name)
6772 goto out;
6773
Willy Tarreau47ca5452012-12-23 20:22:19 +01006774 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02006775 if (args && args[0].type == ARGT_STR) {
6776 int pos = 1;
6777
6778 if (args[1].type == ARGT_SINT)
6779 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02006780
6781 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
6782 goto out;
6783 }
6784 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
6785 goto out;
6786
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006787 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006788 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02006789 ret = 1;
6790out:
Emeric Brunba841a12014-04-30 17:05:08 +02006791 /* SSL_get_peer_certificate, it increase X509 * ref count */
6792 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02006793 X509_free(crt);
6794 return ret;
6795}
Emeric Brun9143d372012-12-20 15:44:16 +01006796
6797/* integer, returns true if current session use a client certificate */
6798static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006799smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01006800{
6801 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006802 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006803 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01006804
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006805 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006806 if (!conn || conn->xprt != &ssl_sock)
6807 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006808 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006809
6810 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01006811 smp->flags |= SMP_F_MAY_CHANGE;
6812 return 0;
6813 }
6814
6815 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006816 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01006817 if (crt) {
6818 X509_free(crt);
6819 }
6820
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006821 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006822 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01006823 return 1;
6824}
6825
Emeric Brunba841a12014-04-30 17:05:08 +02006826/* integer, returns the certificate version
6827 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6828 * should be use.
6829 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02006830static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006831smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006832{
Emeric Brunba841a12014-04-30 17:05:08 +02006833 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006834 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006835 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006836 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006837
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006838 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006839 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02006840 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006841 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006842
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006843 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02006844 smp->flags |= SMP_F_MAY_CHANGE;
6845 return 0;
6846 }
6847
Emeric Brunba841a12014-04-30 17:05:08 +02006848 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006849 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006850 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006851 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02006852 if (!crt)
6853 return 0;
6854
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006855 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02006856 /* SSL_get_peer_certificate increase X509 * ref count */
6857 if (cert_peer)
6858 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006859 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02006860
6861 return 1;
6862}
6863
Emeric Brunba841a12014-04-30 17:05:08 +02006864/* string, returns the certificate's signature algorithm.
6865 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6866 * should be use.
6867 */
Emeric Brun7f56e742012-10-19 18:15:40 +02006868static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006869smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02006870{
Emeric Brunba841a12014-04-30 17:05:08 +02006871 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02006872 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006873 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02006874 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006875 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006876 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02006877
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006878 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006879 if (!conn || conn->xprt != &ssl_sock)
6880 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006881 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006882
6883 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02006884 smp->flags |= SMP_F_MAY_CHANGE;
6885 return 0;
6886 }
6887
Emeric Brunba841a12014-04-30 17:05:08 +02006888 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006889 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006890 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006891 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02006892 if (!crt)
6893 return 0;
6894
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006895 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6896 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02006897
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006898 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6899 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006900 /* SSL_get_peer_certificate increase X509 * ref count */
6901 if (cert_peer)
6902 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006903 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006904 }
Emeric Brun7f56e742012-10-19 18:15:40 +02006905
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006906 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006907 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006908 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006909 /* SSL_get_peer_certificate increase X509 * ref count */
6910 if (cert_peer)
6911 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02006912
6913 return 1;
6914}
6915
Emeric Brunba841a12014-04-30 17:05:08 +02006916/* string, returns the certificate's key algorithm.
6917 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6918 * should be use.
6919 */
Emeric Brun521a0112012-10-22 12:22:55 +02006920static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006921smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02006922{
Emeric Brunba841a12014-04-30 17:05:08 +02006923 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02006924 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006925 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02006926 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006927 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006928 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02006929
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006930 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006931 if (!conn || conn->xprt != &ssl_sock)
6932 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006933 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006934
6935 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02006936 smp->flags |= SMP_F_MAY_CHANGE;
6937 return 0;
6938 }
6939
Emeric Brunba841a12014-04-30 17:05:08 +02006940 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006941 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006942 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006943 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02006944 if (!crt)
6945 return 0;
6946
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006947 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
6948 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02006949
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006950 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
6951 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02006952 /* SSL_get_peer_certificate increase X509 * ref count */
6953 if (cert_peer)
6954 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006955 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02006956 }
Emeric Brun521a0112012-10-22 12:22:55 +02006957
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006958 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01006959 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006960 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02006961 if (cert_peer)
6962 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02006963
6964 return 1;
6965}
6966
Emeric Brun645ae792014-04-30 14:21:06 +02006967/* boolean, returns true if front conn. transport layer is SSL.
6968 * This function is also usable on backend conn if the fetch keyword 5th
6969 * char is 'b'.
6970 */
Willy Tarreau7875d092012-09-10 08:20:03 +02006971static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006972smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006973{
Emeric Bruneb8def92018-02-19 15:59:48 +01006974 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
6975 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006976
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006977 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006978 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02006979 return 1;
6980}
6981
Emeric Brun2525b6b2012-10-18 15:59:43 +02006982/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02006983static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006984smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02006985{
6986#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006987 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006988 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006989
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006990 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006991 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006992 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01006993 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02006994 return 1;
6995#else
6996 return 0;
6997#endif
6998}
6999
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007000/* boolean, returns true if client session has been resumed.
7001 * This function is also usable on backend conn if the fetch keyword 5th
7002 * char is 'b'.
7003 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007004static int
7005smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7006{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007007 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7008 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007009 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007010
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007011
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007012 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007013 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007014 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007015 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007016 return 1;
7017}
7018
Emeric Brun645ae792014-04-30 14:21:06 +02007019/* string, returns the used cipher if front conn. transport layer is SSL.
7020 * This function is also usable on backend conn if the fetch keyword 5th
7021 * char is 'b'.
7022 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007023static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007024smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007025{
Emeric Bruneb8def92018-02-19 15:59:48 +01007026 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7027 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007028 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007029
Willy Tarreaube508f12016-03-10 11:47:01 +01007030 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007031 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007032 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007033 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007034
Olivier Houchard66ab4982019-02-26 18:37:15 +01007035 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007036 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007037 return 0;
7038
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007039 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007040 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007041 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007042
7043 return 1;
7044}
7045
Emeric Brun645ae792014-04-30 14:21:06 +02007046/* integer, returns the algoritm's keysize if front conn. transport layer
7047 * is SSL.
7048 * This function is also usable on backend conn if the fetch keyword 5th
7049 * char is 'b'.
7050 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007051static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007052smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007053{
Emeric Bruneb8def92018-02-19 15:59:48 +01007054 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7055 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007056 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007057 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007058
Emeric Brun589fcad2012-10-16 14:13:26 +02007059 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007060 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007061 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007062 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007063
Olivier Houchard66ab4982019-02-26 18:37:15 +01007064 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007065 return 0;
7066
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007067 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007068 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007069
7070 return 1;
7071}
7072
Emeric Brun645ae792014-04-30 14:21:06 +02007073/* integer, returns the used keysize if front conn. transport layer is SSL.
7074 * This function is also usable on backend conn if the fetch keyword 5th
7075 * char is 'b'.
7076 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007077static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007078smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007079{
Emeric Bruneb8def92018-02-19 15:59:48 +01007080 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7081 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007082 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007083
Emeric Brun589fcad2012-10-16 14:13:26 +02007084 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007085 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7086 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007087 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007088
Olivier Houchard66ab4982019-02-26 18:37:15 +01007089 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007090 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007091 return 0;
7092
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007093 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007094
7095 return 1;
7096}
7097
Bernard Spil13c53f82018-02-15 13:34:58 +01007098#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007099static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007100smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007101{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007102 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007103 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007104
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007105 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007106 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007107
Olivier Houchard6b77f492018-11-22 18:18:29 +01007108 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7109 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007110 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7111 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007112 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007113
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007114 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007115 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007116 (const unsigned char **)&smp->data.u.str.area,
7117 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007118
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007119 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007120 return 0;
7121
7122 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007123}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007124#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007125
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007126#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007127static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007128smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007129{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007130 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007131 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007132
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007133 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007134 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007135
Olivier Houchard6b77f492018-11-22 18:18:29 +01007136 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7137 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7138
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007139 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007140 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007141 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007142
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007143 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007144 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007145 (const unsigned char **)&smp->data.u.str.area,
7146 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007147
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007148 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007149 return 0;
7150
7151 return 1;
7152}
7153#endif
7154
Emeric Brun645ae792014-04-30 14:21:06 +02007155/* string, returns the used protocol if front conn. transport layer is SSL.
7156 * This function is also usable on backend conn if the fetch keyword 5th
7157 * char is 'b'.
7158 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007159static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007160smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007161{
Emeric Bruneb8def92018-02-19 15:59:48 +01007162 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7163 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007164 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007165
Emeric Brun589fcad2012-10-16 14:13:26 +02007166 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007167 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7168 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007169 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007170
Olivier Houchard66ab4982019-02-26 18:37:15 +01007171 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007172 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007173 return 0;
7174
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007175 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007176 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007177 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007178
7179 return 1;
7180}
7181
Willy Tarreau87b09662015-04-03 00:22:06 +02007182/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007183 * This function is also usable on backend conn if the fetch keyword 5th
7184 * char is 'b'.
7185 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007186#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007187static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007188smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007189{
Emeric Bruneb8def92018-02-19 15:59:48 +01007190 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7191 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007192 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007193 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007194
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007195 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007196 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007197
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007198 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7199 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007200 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007201
Olivier Houchard66ab4982019-02-26 18:37:15 +01007202 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007203 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007204 return 0;
7205
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007206 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7207 (unsigned int *)&smp->data.u.str.data);
7208 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007209 return 0;
7210
7211 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007212}
Patrick Hemmer41966772018-04-28 19:15:48 -04007213#endif
7214
Emeric Brunfe68f682012-10-16 14:59:28 +02007215
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007216#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
Patrick Hemmere0275472018-04-28 19:15:51 -04007217static int
7218smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7219{
7220 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7221 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7222 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007223 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007224 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007225
7226 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7227 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007228 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007229
Olivier Houchard66ab4982019-02-26 18:37:15 +01007230 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007231 if (!ssl_sess)
7232 return 0;
7233
7234 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007235 data->data = SSL_SESSION_get_master_key(ssl_sess,
7236 (unsigned char *) data->area,
7237 data->size);
7238 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007239 return 0;
7240
7241 smp->flags = 0;
7242 smp->data.type = SMP_T_BIN;
7243 smp->data.u.str = *data;
7244
7245 return 1;
7246}
7247#endif
7248
Patrick Hemmer41966772018-04-28 19:15:48 -04007249#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007250static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007251smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007252{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007253 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007254 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007255
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007256 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007257 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007258
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007259 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007260 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7261 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007262 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007263
Olivier Houchard66ab4982019-02-26 18:37:15 +01007264 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007265 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007266 return 0;
7267
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007268 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007269 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007270}
Patrick Hemmer41966772018-04-28 19:15:48 -04007271#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007272
David Sc1ad52e2014-04-08 18:48:47 -04007273static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007274smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7275{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007276 struct connection *conn;
7277 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007278 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007279
7280 conn = objt_conn(smp->sess->origin);
7281 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7282 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007283 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007284
Olivier Houchard66ab4982019-02-26 18:37:15 +01007285 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007286 if (!capture)
7287 return 0;
7288
7289 smp->flags = SMP_F_CONST;
7290 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007291 smp->data.u.str.area = capture->ciphersuite;
7292 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007293 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007294}
7295
7296static int
7297smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7298{
Willy Tarreau83061a82018-07-13 11:56:34 +02007299 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007300
7301 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7302 return 0;
7303
7304 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007305 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007306 smp->data.type = SMP_T_BIN;
7307 smp->data.u.str = *data;
7308 return 1;
7309}
7310
7311static int
7312smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7313{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007314 struct connection *conn;
7315 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007316 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007317
7318 conn = objt_conn(smp->sess->origin);
7319 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7320 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007321 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007322
Olivier Houchard66ab4982019-02-26 18:37:15 +01007323 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007324 if (!capture)
7325 return 0;
7326
7327 smp->data.type = SMP_T_SINT;
7328 smp->data.u.sint = capture->xxh64;
7329 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007330}
7331
7332static int
7333smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7334{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007335#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007336 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007337 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007338
7339 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7340 return 0;
7341
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007342 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007343 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007344 const char *str;
7345 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007346 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007347 uint16_t id = (bin[0] << 8) | bin[1];
7348#if defined(OPENSSL_IS_BORINGSSL)
7349 cipher = SSL_get_cipher_by_value(id);
7350#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007351 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007352 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7353 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007354#endif
7355 str = SSL_CIPHER_get_name(cipher);
7356 if (!str || strcmp(str, "(NONE)") == 0)
7357 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007358 else
7359 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7360 }
7361 smp->data.type = SMP_T_STR;
7362 smp->data.u.str = *data;
7363 return 1;
7364#else
7365 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7366#endif
7367}
7368
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007369#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007370static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007371smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007372{
Emeric Bruneb8def92018-02-19 15:59:48 +01007373 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7374 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007375 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007376 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007377 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007378
7379 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007380 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7381 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007382 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007383
7384 if (!(conn->flags & CO_FL_CONNECTED)) {
7385 smp->flags |= SMP_F_MAY_CHANGE;
7386 return 0;
7387 }
7388
7389 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007390 if (!SSL_session_reused(ctx->ssl))
7391 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007392 finished_trash->area,
7393 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007394 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007395 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007396 finished_trash->area,
7397 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007398
7399 if (!finished_len)
7400 return 0;
7401
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007402 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007403 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007404 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007405
7406 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007407}
Patrick Hemmer41966772018-04-28 19:15:48 -04007408#endif
David Sc1ad52e2014-04-08 18:48:47 -04007409
Emeric Brun2525b6b2012-10-18 15:59:43 +02007410/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007411static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007412smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007413{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007414 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007415 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007416
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007417 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007418 if (!conn || conn->xprt != &ssl_sock)
7419 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007420 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007421
7422 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007423 smp->flags = SMP_F_MAY_CHANGE;
7424 return 0;
7425 }
7426
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007427 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007428 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007429 smp->flags = 0;
7430
7431 return 1;
7432}
7433
Emeric Brun2525b6b2012-10-18 15:59:43 +02007434/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007435static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007436smp_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 +02007437{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007438 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007439 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007440
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007441 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007442 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007443 return 0;
7444
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007445 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007446 smp->flags = SMP_F_MAY_CHANGE;
7447 return 0;
7448 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007449 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007450
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007451 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007452 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007453 smp->flags = 0;
7454
7455 return 1;
7456}
7457
Emeric Brun2525b6b2012-10-18 15:59:43 +02007458/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007459static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007460smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007461{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007462 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007463 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007464
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007465 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007466 if (!conn || conn->xprt != &ssl_sock)
7467 return 0;
7468
7469 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007470 smp->flags = SMP_F_MAY_CHANGE;
7471 return 0;
7472 }
7473
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007474 ctx = conn->xprt_ctx;
7475
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007476 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007477 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007478 smp->flags = 0;
7479
7480 return 1;
7481}
7482
Emeric Brun2525b6b2012-10-18 15:59:43 +02007483/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007484static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007485smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007486{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007487 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007488 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007489
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007490 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007491 if (!conn || conn->xprt != &ssl_sock)
7492 return 0;
7493
7494 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007495 smp->flags = SMP_F_MAY_CHANGE;
7496 return 0;
7497 }
7498
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007499 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007500 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007501 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007502
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007503 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007504 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007505 smp->flags = 0;
7506
7507 return 1;
7508}
7509
Emeric Brunfb510ea2012-10-05 12:00:26 +02007510/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007511static 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 +02007512{
7513 if (!*args[cur_arg + 1]) {
7514 if (err)
7515 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7516 return ERR_ALERT | ERR_FATAL;
7517 }
7518
Willy Tarreauef934602016-12-22 23:12:01 +01007519 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7520 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007521 else
7522 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007523
Emeric Brund94b3fe2012-09-20 18:23:56 +02007524 return 0;
7525}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007526static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7527{
7528 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7529}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007530
Christopher Faulet31af49d2015-06-09 17:29:50 +02007531/* parse the "ca-sign-file" bind keyword */
7532static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7533{
7534 if (!*args[cur_arg + 1]) {
7535 if (err)
7536 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7537 return ERR_ALERT | ERR_FATAL;
7538 }
7539
Willy Tarreauef934602016-12-22 23:12:01 +01007540 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7541 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007542 else
7543 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7544
7545 return 0;
7546}
7547
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007548/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007549static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7550{
7551 if (!*args[cur_arg + 1]) {
7552 if (err)
7553 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7554 return ERR_ALERT | ERR_FATAL;
7555 }
7556 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7557 return 0;
7558}
7559
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007560/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007561static 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 +02007562{
7563 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007564 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007565 return ERR_ALERT | ERR_FATAL;
7566 }
7567
Emeric Brun76d88952012-10-05 15:47:31 +02007568 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007569 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007570 return 0;
7571}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007572static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7573{
7574 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7575}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007576
Willy Tarreau5db847a2019-05-09 14:13:35 +02007577#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007578/* parse the "ciphersuites" bind keyword */
7579static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7580{
7581 if (!*args[cur_arg + 1]) {
7582 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7583 return ERR_ALERT | ERR_FATAL;
7584 }
7585
7586 free(conf->ciphersuites);
7587 conf->ciphersuites = strdup(args[cur_arg + 1]);
7588 return 0;
7589}
7590static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7591{
7592 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7593}
7594#endif
7595
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007596/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007597static 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 +02007598{
Willy Tarreau38011032013-08-13 16:59:39 +02007599 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007600
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007601 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007602 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007603 return ERR_ALERT | ERR_FATAL;
7604 }
7605
Willy Tarreauef934602016-12-22 23:12:01 +01007606 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7607 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007608 memprintf(err, "'%s' : path too long", args[cur_arg]);
7609 return ERR_ALERT | ERR_FATAL;
7610 }
Willy Tarreauef934602016-12-22 23:12:01 +01007611 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007612 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007613 return ERR_ALERT | ERR_FATAL;
7614
7615 return 0;
7616 }
7617
Willy Tarreau03209342016-12-22 17:08:28 +01007618 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007619 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02007620
7621 return 0;
7622}
7623
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007624/* parse the "crt-list" bind keyword */
7625static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7626{
7627 if (!*args[cur_arg + 1]) {
7628 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
7629 return ERR_ALERT | ERR_FATAL;
7630 }
7631
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007632 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02007633 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007634 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02007635 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01007636
7637 return 0;
7638}
7639
Emeric Brunfb510ea2012-10-05 12:00:26 +02007640/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007641static 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 +02007642{
Emeric Brun051cdab2012-10-02 19:25:50 +02007643#ifndef X509_V_FLAG_CRL_CHECK
7644 if (err)
7645 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
7646 return ERR_ALERT | ERR_FATAL;
7647#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02007648 if (!*args[cur_arg + 1]) {
7649 if (err)
7650 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
7651 return ERR_ALERT | ERR_FATAL;
7652 }
Emeric Brun2b58d042012-09-20 17:10:03 +02007653
Willy Tarreauef934602016-12-22 23:12:01 +01007654 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7655 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007656 else
7657 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007658
Emeric Brun2b58d042012-09-20 17:10:03 +02007659 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02007660#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02007661}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007662static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7663{
7664 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
7665}
Emeric Brun2b58d042012-09-20 17:10:03 +02007666
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007667/* parse the "curves" bind keyword keyword */
7668static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7669{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007670#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01007671 if (!*args[cur_arg + 1]) {
7672 if (err)
7673 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
7674 return ERR_ALERT | ERR_FATAL;
7675 }
7676 conf->curves = strdup(args[cur_arg + 1]);
7677 return 0;
7678#else
7679 if (err)
7680 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
7681 return ERR_ALERT | ERR_FATAL;
7682#endif
7683}
7684static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7685{
7686 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
7687}
7688
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007689/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007690static 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 +02007691{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007692#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02007693 if (err)
7694 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
7695 return ERR_ALERT | ERR_FATAL;
7696#elif defined(OPENSSL_NO_ECDH)
7697 if (err)
7698 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
7699 return ERR_ALERT | ERR_FATAL;
7700#else
7701 if (!*args[cur_arg + 1]) {
7702 if (err)
7703 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
7704 return ERR_ALERT | ERR_FATAL;
7705 }
7706
7707 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007708
7709 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02007710#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007711}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007712static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7713{
7714 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
7715}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007716
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007717/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02007718static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7719{
7720 int code;
7721 char *p = args[cur_arg + 1];
7722 unsigned long long *ignerr = &conf->crt_ignerr;
7723
7724 if (!*p) {
7725 if (err)
7726 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
7727 return ERR_ALERT | ERR_FATAL;
7728 }
7729
7730 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
7731 ignerr = &conf->ca_ignerr;
7732
7733 if (strcmp(p, "all") == 0) {
7734 *ignerr = ~0ULL;
7735 return 0;
7736 }
7737
7738 while (p) {
7739 code = atoi(p);
7740 if ((code <= 0) || (code > 63)) {
7741 if (err)
7742 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
7743 args[cur_arg], code, args[cur_arg + 1]);
7744 return ERR_ALERT | ERR_FATAL;
7745 }
7746 *ignerr |= 1ULL << code;
7747 p = strchr(p, ',');
7748 if (p)
7749 p++;
7750 }
7751
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007752 return 0;
7753}
7754
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007755/* parse tls_method_options "no-xxx" and "force-xxx" */
7756static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007757{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007758 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007759 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007760 p = strchr(arg, '-');
7761 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007762 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007763 p++;
7764 if (!strcmp(p, "sslv3"))
7765 v = CONF_SSLV3;
7766 else if (!strcmp(p, "tlsv10"))
7767 v = CONF_TLSV10;
7768 else if (!strcmp(p, "tlsv11"))
7769 v = CONF_TLSV11;
7770 else if (!strcmp(p, "tlsv12"))
7771 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02007772 else if (!strcmp(p, "tlsv13"))
7773 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007774 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007775 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007776 if (!strncmp(arg, "no-", 3))
7777 methods->flags |= methodVersions[v].flag;
7778 else if (!strncmp(arg, "force-", 6))
7779 methods->min = methods->max = v;
7780 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007781 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007782 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007783 fail:
7784 if (err)
7785 memprintf(err, "'%s' : option not implemented", arg);
7786 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02007787}
7788
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007789static 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 +02007790{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007791 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007792}
7793
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007794static 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 +02007795{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007796 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
7797}
7798
7799/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
7800static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
7801{
7802 uint16_t i, v = 0;
7803 char *argv = args[cur_arg + 1];
7804 if (!*argv) {
7805 if (err)
7806 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
7807 return ERR_ALERT | ERR_FATAL;
7808 }
7809 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
7810 if (!strcmp(argv, methodVersions[i].name))
7811 v = i;
7812 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007813 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007814 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02007815 return ERR_ALERT | ERR_FATAL;
7816 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007817 if (!strcmp("ssl-min-ver", args[cur_arg]))
7818 methods->min = v;
7819 else if (!strcmp("ssl-max-ver", args[cur_arg]))
7820 methods->max = v;
7821 else {
7822 if (err)
7823 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
7824 return ERR_ALERT | ERR_FATAL;
7825 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007826 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007827}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02007828
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02007829static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7830{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007831#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01007832 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 +02007833#endif
7834 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
7835}
7836
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007837static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7838{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007839 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02007840}
7841
7842static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
7843{
7844 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
7845}
7846
Emeric Brun2d0c4822012-10-02 13:45:20 +02007847/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007848static 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 +02007849{
Emeric Brun89675492012-10-05 13:48:26 +02007850 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02007851 return 0;
7852}
Emeric Brun2d0c4822012-10-02 13:45:20 +02007853
Olivier Houchardc2aae742017-09-22 18:26:28 +02007854/* parse the "allow-0rtt" bind keyword */
7855static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7856{
7857 conf->early_data = 1;
7858 return 0;
7859}
7860
7861static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7862{
Olivier Houchard9679ac92017-10-27 14:58:08 +02007863 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02007864 return 0;
7865}
7866
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007867/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007868static 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 +02007869{
Bernard Spil13c53f82018-02-15 13:34:58 +01007870#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007871 char *p1, *p2;
7872
7873 if (!*args[cur_arg + 1]) {
7874 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
7875 return ERR_ALERT | ERR_FATAL;
7876 }
7877
7878 free(conf->npn_str);
7879
Willy Tarreau3724da12016-02-12 17:11:12 +01007880 /* the NPN string is built as a suite of (<len> <name>)*,
7881 * so we reuse each comma to store the next <len> and need
7882 * one more for the end of the string.
7883 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007884 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01007885 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007886 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
7887
7888 /* replace commas with the name length */
7889 p1 = conf->npn_str;
7890 p2 = p1 + 1;
7891 while (1) {
7892 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
7893 if (!p2)
7894 p2 = p1 + 1 + strlen(p1 + 1);
7895
7896 if (p2 - (p1 + 1) > 255) {
7897 *p2 = '\0';
7898 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7899 return ERR_ALERT | ERR_FATAL;
7900 }
7901
7902 *p1 = p2 - (p1 + 1);
7903 p1 = p2;
7904
7905 if (!*p2)
7906 break;
7907
7908 *(p2++) = '\0';
7909 }
7910 return 0;
7911#else
7912 if (err)
7913 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
7914 return ERR_ALERT | ERR_FATAL;
7915#endif
7916}
7917
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007918static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7919{
7920 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
7921}
7922
Willy Tarreauab861d32013-04-02 02:30:41 +02007923/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007924static 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 +02007925{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007926#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007927 char *p1, *p2;
7928
7929 if (!*args[cur_arg + 1]) {
7930 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
7931 return ERR_ALERT | ERR_FATAL;
7932 }
7933
7934 free(conf->alpn_str);
7935
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007936 /* the ALPN string is built as a suite of (<len> <name>)*,
7937 * so we reuse each comma to store the next <len> and need
7938 * one more for the end of the string.
7939 */
Willy Tarreauab861d32013-04-02 02:30:41 +02007940 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01007941 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02007942 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
7943
7944 /* replace commas with the name length */
7945 p1 = conf->alpn_str;
7946 p2 = p1 + 1;
7947 while (1) {
7948 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
7949 if (!p2)
7950 p2 = p1 + 1 + strlen(p1 + 1);
7951
7952 if (p2 - (p1 + 1) > 255) {
7953 *p2 = '\0';
7954 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
7955 return ERR_ALERT | ERR_FATAL;
7956 }
7957
7958 *p1 = p2 - (p1 + 1);
7959 p1 = p2;
7960
7961 if (!*p2)
7962 break;
7963
7964 *(p2++) = '\0';
7965 }
7966 return 0;
7967#else
7968 if (err)
7969 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
7970 return ERR_ALERT | ERR_FATAL;
7971#endif
7972}
7973
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007974static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7975{
7976 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
7977}
7978
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007979/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007980static 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 +02007981{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01007982 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007983 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02007984
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007985 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
7986 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Willy Tarreau5db847a2019-05-09 14:13:35 +02007987#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007988 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
7989 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
7990#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01007991 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02007992 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
7993 if (!conf->ssl_conf.ssl_methods.min)
7994 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
7995 if (!conf->ssl_conf.ssl_methods.max)
7996 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02007997
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007998 return 0;
7999}
8000
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008001/* parse the "prefer-client-ciphers" bind keyword */
8002static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8003{
8004 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8005 return 0;
8006}
8007
Christopher Faulet31af49d2015-06-09 17:29:50 +02008008/* parse the "generate-certificates" bind keyword */
8009static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8010{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008011#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008012 conf->generate_certs = 1;
8013#else
8014 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8015 err && *err ? *err : "");
8016#endif
8017 return 0;
8018}
8019
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008020/* parse the "strict-sni" bind keyword */
8021static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8022{
8023 conf->strict_sni = 1;
8024 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008025}
8026
8027/* parse the "tls-ticket-keys" bind keyword */
8028static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8029{
8030#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8031 FILE *f;
8032 int i = 0;
8033 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008034 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008035
8036 if (!*args[cur_arg + 1]) {
8037 if (err)
8038 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
8039 return ERR_ALERT | ERR_FATAL;
8040 }
8041
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008042 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008043 if (keys_ref) {
8044 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008045 conf->keys_ref = keys_ref;
8046 return 0;
8047 }
8048
Vincent Bernat02779b62016-04-03 13:48:43 +02008049 keys_ref = malloc(sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008050 if (!keys_ref) {
8051 if (err)
8052 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8053 return ERR_ALERT | ERR_FATAL;
8054 }
8055
Emeric Brun9e754772019-01-10 17:51:55 +01008056 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008057 if (!keys_ref->tlskeys) {
8058 free(keys_ref);
8059 if (err)
8060 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8061 return ERR_ALERT | ERR_FATAL;
8062 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008063
8064 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Emeric Brun09852f72019-01-10 10:51:13 +01008065 free(keys_ref->tlskeys);
8066 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008067 if (err)
8068 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
8069 return ERR_ALERT | ERR_FATAL;
8070 }
8071
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008072 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008073 if (!keys_ref->filename) {
8074 free(keys_ref->tlskeys);
8075 free(keys_ref);
8076 if (err)
8077 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8078 return ERR_ALERT | ERR_FATAL;
8079 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008080
Emeric Brun9e754772019-01-10 17:51:55 +01008081 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008082 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8083 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008084 int dec_size;
8085
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008086 /* Strip newline characters from the end */
8087 if(thisline[len - 1] == '\n')
8088 thisline[--len] = 0;
8089
8090 if(thisline[len - 1] == '\r')
8091 thisline[--len] = 0;
8092
Emeric Brun9e754772019-01-10 17:51:55 +01008093 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8094 if (dec_size < 0) {
Emeric Brun09852f72019-01-10 10:51:13 +01008095 free(keys_ref->filename);
8096 free(keys_ref->tlskeys);
8097 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008098 if (err)
8099 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02008100 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008101 return ERR_ALERT | ERR_FATAL;
8102 }
Emeric Brun9e754772019-01-10 17:51:55 +01008103 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8104 keys_ref->key_size_bits = 128;
8105 }
8106 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8107 keys_ref->key_size_bits = 256;
8108 }
8109 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8110 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8111 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
8112 free(keys_ref->filename);
8113 free(keys_ref->tlskeys);
8114 free(keys_ref);
8115 if (err)
8116 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
8117 fclose(f);
8118 return ERR_ALERT | ERR_FATAL;
8119 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008120 i++;
8121 }
8122
8123 if (i < TLS_TICKETS_NO) {
Emeric Brun09852f72019-01-10 10:51:13 +01008124 free(keys_ref->filename);
8125 free(keys_ref->tlskeys);
8126 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008127 if (err)
8128 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 +02008129 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008130 return ERR_ALERT | ERR_FATAL;
8131 }
8132
8133 fclose(f);
8134
8135 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008136 i -= 2;
8137 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008138 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008139 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008140 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008141 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008142
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008143 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8144
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008145 return 0;
8146#else
8147 if (err)
8148 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8149 return ERR_ALERT | ERR_FATAL;
8150#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008151}
8152
Emeric Brund94b3fe2012-09-20 18:23:56 +02008153/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008154static 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 +02008155{
8156 if (!*args[cur_arg + 1]) {
8157 if (err)
8158 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8159 return ERR_ALERT | ERR_FATAL;
8160 }
8161
8162 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008163 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008164 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008165 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008166 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008167 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008168 else {
8169 if (err)
8170 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8171 args[cur_arg], args[cur_arg + 1]);
8172 return ERR_ALERT | ERR_FATAL;
8173 }
8174
8175 return 0;
8176}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008177static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8178{
8179 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8180}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008181
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008182/* parse the "no-ca-names" bind keyword */
8183static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8184{
8185 conf->no_ca_names = 1;
8186 return 0;
8187}
8188static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8189{
8190 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8191}
8192
Willy Tarreau92faadf2012-10-10 23:04:25 +02008193/************** "server" keywords ****************/
8194
Olivier Houchardc7566002018-11-20 23:33:50 +01008195/* parse the "npn" bind keyword */
8196static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8197{
8198#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8199 char *p1, *p2;
8200
8201 if (!*args[*cur_arg + 1]) {
8202 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8203 return ERR_ALERT | ERR_FATAL;
8204 }
8205
8206 free(newsrv->ssl_ctx.npn_str);
8207
8208 /* the NPN string is built as a suite of (<len> <name>)*,
8209 * so we reuse each comma to store the next <len> and need
8210 * one more for the end of the string.
8211 */
8212 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8213 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8214 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8215 newsrv->ssl_ctx.npn_len);
8216
8217 /* replace commas with the name length */
8218 p1 = newsrv->ssl_ctx.npn_str;
8219 p2 = p1 + 1;
8220 while (1) {
8221 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8222 newsrv->ssl_ctx.npn_len - (p1 + 1));
8223 if (!p2)
8224 p2 = p1 + 1 + strlen(p1 + 1);
8225
8226 if (p2 - (p1 + 1) > 255) {
8227 *p2 = '\0';
8228 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8229 return ERR_ALERT | ERR_FATAL;
8230 }
8231
8232 *p1 = p2 - (p1 + 1);
8233 p1 = p2;
8234
8235 if (!*p2)
8236 break;
8237
8238 *(p2++) = '\0';
8239 }
8240 return 0;
8241#else
8242 if (err)
8243 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8244 return ERR_ALERT | ERR_FATAL;
8245#endif
8246}
8247
Olivier Houchard92150142018-12-21 19:47:01 +01008248/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008249static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8250{
8251#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8252 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008253 char **alpn_str;
8254 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008255
Olivier Houchard92150142018-12-21 19:47:01 +01008256 if (*args[*cur_arg] == 'c') {
8257 alpn_str = &newsrv->check.alpn_str;
8258 alpn_len = &newsrv->check.alpn_len;
8259 } else {
8260 alpn_str = &newsrv->ssl_ctx.alpn_str;
8261 alpn_len = &newsrv->ssl_ctx.alpn_len;
8262
8263 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008264 if (!*args[*cur_arg + 1]) {
8265 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8266 return ERR_ALERT | ERR_FATAL;
8267 }
8268
Olivier Houchard92150142018-12-21 19:47:01 +01008269 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008270
8271 /* the ALPN string is built as a suite of (<len> <name>)*,
8272 * so we reuse each comma to store the next <len> and need
8273 * one more for the end of the string.
8274 */
Olivier Houchard92150142018-12-21 19:47:01 +01008275 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8276 *alpn_str = calloc(1, *alpn_len + 1);
8277 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008278
8279 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008280 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008281 p2 = p1 + 1;
8282 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008283 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008284 if (!p2)
8285 p2 = p1 + 1 + strlen(p1 + 1);
8286
8287 if (p2 - (p1 + 1) > 255) {
8288 *p2 = '\0';
8289 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8290 return ERR_ALERT | ERR_FATAL;
8291 }
8292
8293 *p1 = p2 - (p1 + 1);
8294 p1 = p2;
8295
8296 if (!*p2)
8297 break;
8298
8299 *(p2++) = '\0';
8300 }
8301 return 0;
8302#else
8303 if (err)
8304 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8305 return ERR_ALERT | ERR_FATAL;
8306#endif
8307}
8308
Emeric Brunef42d922012-10-11 16:11:36 +02008309/* parse the "ca-file" server keyword */
8310static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8311{
8312 if (!*args[*cur_arg + 1]) {
8313 if (err)
8314 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8315 return ERR_ALERT | ERR_FATAL;
8316 }
8317
Willy Tarreauef934602016-12-22 23:12:01 +01008318 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8319 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008320 else
8321 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8322
8323 return 0;
8324}
8325
Olivier Houchard9130a962017-10-17 17:33:43 +02008326/* parse the "check-sni" server keyword */
8327static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8328{
8329 if (!*args[*cur_arg + 1]) {
8330 if (err)
8331 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8332 return ERR_ALERT | ERR_FATAL;
8333 }
8334
8335 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8336 if (!newsrv->check.sni) {
8337 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8338 return ERR_ALERT | ERR_FATAL;
8339 }
8340 return 0;
8341
8342}
8343
Willy Tarreau92faadf2012-10-10 23:04:25 +02008344/* parse the "check-ssl" server keyword */
8345static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8346{
8347 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008348 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8349 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau5db847a2019-05-09 14:13:35 +02008350#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008351 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8352 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8353#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008354 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008355 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8356 if (!newsrv->ssl_ctx.methods.min)
8357 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8358 if (!newsrv->ssl_ctx.methods.max)
8359 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8360
Willy Tarreau92faadf2012-10-10 23:04:25 +02008361 return 0;
8362}
8363
8364/* parse the "ciphers" server keyword */
8365static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8366{
8367 if (!*args[*cur_arg + 1]) {
8368 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8369 return ERR_ALERT | ERR_FATAL;
8370 }
8371
8372 free(newsrv->ssl_ctx.ciphers);
8373 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8374 return 0;
8375}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008376
Willy Tarreau5db847a2019-05-09 14:13:35 +02008377#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008378/* parse the "ciphersuites" server keyword */
8379static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8380{
8381 if (!*args[*cur_arg + 1]) {
8382 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8383 return ERR_ALERT | ERR_FATAL;
8384 }
8385
8386 free(newsrv->ssl_ctx.ciphersuites);
8387 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8388 return 0;
8389}
8390#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008391
Emeric Brunef42d922012-10-11 16:11:36 +02008392/* parse the "crl-file" server keyword */
8393static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8394{
8395#ifndef X509_V_FLAG_CRL_CHECK
8396 if (err)
8397 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8398 return ERR_ALERT | ERR_FATAL;
8399#else
8400 if (!*args[*cur_arg + 1]) {
8401 if (err)
8402 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8403 return ERR_ALERT | ERR_FATAL;
8404 }
8405
Willy Tarreauef934602016-12-22 23:12:01 +01008406 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8407 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008408 else
8409 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8410
8411 return 0;
8412#endif
8413}
8414
Emeric Bruna7aa3092012-10-26 12:58:00 +02008415/* parse the "crt" server keyword */
8416static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8417{
8418 if (!*args[*cur_arg + 1]) {
8419 if (err)
8420 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8421 return ERR_ALERT | ERR_FATAL;
8422 }
8423
Willy Tarreauef934602016-12-22 23:12:01 +01008424 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008425 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008426 else
8427 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8428
8429 return 0;
8430}
Emeric Brunef42d922012-10-11 16:11:36 +02008431
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008432/* parse the "no-check-ssl" server keyword */
8433static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8434{
8435 newsrv->check.use_ssl = 0;
8436 free(newsrv->ssl_ctx.ciphers);
8437 newsrv->ssl_ctx.ciphers = NULL;
8438 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8439 return 0;
8440}
8441
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008442/* parse the "no-send-proxy-v2-ssl" server keyword */
8443static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8444{
8445 newsrv->pp_opts &= ~SRV_PP_V2;
8446 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8447 return 0;
8448}
8449
8450/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8451static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8452{
8453 newsrv->pp_opts &= ~SRV_PP_V2;
8454 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8455 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8456 return 0;
8457}
8458
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008459/* parse the "no-ssl" server keyword */
8460static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8461{
8462 newsrv->use_ssl = 0;
8463 free(newsrv->ssl_ctx.ciphers);
8464 newsrv->ssl_ctx.ciphers = NULL;
8465 return 0;
8466}
8467
Olivier Houchard522eea72017-11-03 16:27:47 +01008468/* parse the "allow-0rtt" server keyword */
8469static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8470{
8471 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8472 return 0;
8473}
8474
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008475/* parse the "no-ssl-reuse" server keyword */
8476static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8477{
8478 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8479 return 0;
8480}
8481
Emeric Brunf9c5c472012-10-11 15:28:34 +02008482/* parse the "no-tls-tickets" server keyword */
8483static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8484{
8485 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8486 return 0;
8487}
David Safb76832014-05-08 23:42:08 -04008488/* parse the "send-proxy-v2-ssl" server keyword */
8489static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8490{
8491 newsrv->pp_opts |= SRV_PP_V2;
8492 newsrv->pp_opts |= SRV_PP_V2_SSL;
8493 return 0;
8494}
8495
8496/* parse the "send-proxy-v2-ssl-cn" server keyword */
8497static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8498{
8499 newsrv->pp_opts |= SRV_PP_V2;
8500 newsrv->pp_opts |= SRV_PP_V2_SSL;
8501 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8502 return 0;
8503}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008504
Willy Tarreau732eac42015-07-09 11:40:25 +02008505/* parse the "sni" server keyword */
8506static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8507{
8508#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8509 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8510 return ERR_ALERT | ERR_FATAL;
8511#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008512 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008513
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008514 arg = args[*cur_arg + 1];
8515 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008516 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8517 return ERR_ALERT | ERR_FATAL;
8518 }
8519
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008520 free(newsrv->sni_expr);
8521 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008522
Willy Tarreau732eac42015-07-09 11:40:25 +02008523 return 0;
8524#endif
8525}
8526
Willy Tarreau92faadf2012-10-10 23:04:25 +02008527/* parse the "ssl" server keyword */
8528static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8529{
8530 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008531 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8532 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau5db847a2019-05-09 14:13:35 +02008533#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008534 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8535 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8536#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008537 return 0;
8538}
8539
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008540/* parse the "ssl-reuse" server keyword */
8541static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8542{
8543 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8544 return 0;
8545}
8546
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008547/* parse the "tls-tickets" server keyword */
8548static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8549{
8550 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8551 return 0;
8552}
8553
Emeric Brunef42d922012-10-11 16:11:36 +02008554/* parse the "verify" server keyword */
8555static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8556{
8557 if (!*args[*cur_arg + 1]) {
8558 if (err)
8559 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8560 return ERR_ALERT | ERR_FATAL;
8561 }
8562
8563 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008564 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008565 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008566 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008567 else {
8568 if (err)
8569 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8570 args[*cur_arg], args[*cur_arg + 1]);
8571 return ERR_ALERT | ERR_FATAL;
8572 }
8573
Evan Broderbe554312013-06-27 00:05:25 -07008574 return 0;
8575}
8576
8577/* parse the "verifyhost" server keyword */
8578static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8579{
8580 if (!*args[*cur_arg + 1]) {
8581 if (err)
8582 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8583 return ERR_ALERT | ERR_FATAL;
8584 }
8585
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008586 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008587 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8588
Emeric Brunef42d922012-10-11 16:11:36 +02008589 return 0;
8590}
8591
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008592/* parse the "ssl-default-bind-options" keyword in global section */
8593static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8594 struct proxy *defpx, const char *file, int line,
8595 char **err) {
8596 int i = 1;
8597
8598 if (*(args[i]) == 0) {
8599 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8600 return -1;
8601 }
8602 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008603 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008604 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008605 else if (!strcmp(args[i], "prefer-client-ciphers"))
8606 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008607 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8608 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8609 i++;
8610 else {
8611 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8612 return -1;
8613 }
8614 }
8615 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008616 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8617 return -1;
8618 }
8619 i++;
8620 }
8621 return 0;
8622}
8623
8624/* parse the "ssl-default-server-options" keyword in global section */
8625static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
8626 struct proxy *defpx, const char *file, int line,
8627 char **err) {
8628 int i = 1;
8629
8630 if (*(args[i]) == 0) {
8631 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8632 return -1;
8633 }
8634 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008635 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008636 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008637 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8638 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
8639 i++;
8640 else {
8641 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8642 return -1;
8643 }
8644 }
8645 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008646 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
8647 return -1;
8648 }
8649 i++;
8650 }
8651 return 0;
8652}
8653
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008654/* parse the "ca-base" / "crt-base" keywords in global section.
8655 * Returns <0 on alert, >0 on warning, 0 on success.
8656 */
8657static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
8658 struct proxy *defpx, const char *file, int line,
8659 char **err)
8660{
8661 char **target;
8662
Willy Tarreauef934602016-12-22 23:12:01 +01008663 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008664
8665 if (too_many_args(1, args, err, NULL))
8666 return -1;
8667
8668 if (*target) {
8669 memprintf(err, "'%s' already specified.", args[0]);
8670 return -1;
8671 }
8672
8673 if (*(args[1]) == 0) {
8674 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
8675 return -1;
8676 }
8677 *target = strdup(args[1]);
8678 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008679}
8680
8681/* parse the "ssl-mode-async" keyword in global section.
8682 * Returns <0 on alert, >0 on warning, 0 on success.
8683 */
8684static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
8685 struct proxy *defpx, const char *file, int line,
8686 char **err)
8687{
Willy Tarreau5db847a2019-05-09 14:13:35 +02008688#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008689 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01008690 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008691 return 0;
8692#else
8693 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
8694 return -1;
8695#endif
8696}
8697
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008698#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008699static int ssl_check_async_engine_count(void) {
8700 int err_code = 0;
8701
Emeric Brun3854e012017-05-17 20:42:48 +02008702 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01008703 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00008704 err_code = ERR_ABORT;
8705 }
8706 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01008707}
8708
Grant Zhang872f9c22017-01-21 01:10:18 +00008709/* parse the "ssl-engine" keyword in global section.
8710 * Returns <0 on alert, >0 on warning, 0 on success.
8711 */
8712static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
8713 struct proxy *defpx, const char *file, int line,
8714 char **err)
8715{
8716 char *algo;
8717 int ret = -1;
8718
8719 if (*(args[1]) == 0) {
8720 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
8721 return ret;
8722 }
8723
8724 if (*(args[2]) == 0) {
8725 /* if no list of algorithms is given, it defaults to ALL */
8726 algo = strdup("ALL");
8727 goto add_engine;
8728 }
8729
8730 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
8731 if (strcmp(args[2], "algo") != 0) {
8732 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
8733 return ret;
8734 }
8735
8736 if (*(args[3]) == 0) {
8737 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
8738 return ret;
8739 }
8740 algo = strdup(args[3]);
8741
8742add_engine:
8743 if (ssl_init_single_engine(args[1], algo)==0) {
8744 openssl_engines_initialized++;
8745 ret = 0;
8746 }
8747 free(algo);
8748 return ret;
8749}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02008750#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00008751
Willy Tarreauf22e9682016-12-21 23:23:19 +01008752/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
8753 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8754 */
8755static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
8756 struct proxy *defpx, const char *file, int line,
8757 char **err)
8758{
8759 char **target;
8760
Willy Tarreauef934602016-12-22 23:12:01 +01008761 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01008762
8763 if (too_many_args(1, args, err, NULL))
8764 return -1;
8765
8766 if (*(args[1]) == 0) {
8767 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8768 return -1;
8769 }
8770
8771 free(*target);
8772 *target = strdup(args[1]);
8773 return 0;
8774}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008775
Willy Tarreau5db847a2019-05-09 14:13:35 +02008776#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008777/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
8778 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
8779 */
8780static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
8781 struct proxy *defpx, const char *file, int line,
8782 char **err)
8783{
8784 char **target;
8785
8786 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
8787
8788 if (too_many_args(1, args, err, NULL))
8789 return -1;
8790
8791 if (*(args[1]) == 0) {
8792 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
8793 return -1;
8794 }
8795
8796 free(*target);
8797 *target = strdup(args[1]);
8798 return 0;
8799}
8800#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01008801
Willy Tarreau9ceda382016-12-21 23:13:03 +01008802/* parse various global tune.ssl settings consisting in positive integers.
8803 * Returns <0 on alert, >0 on warning, 0 on success.
8804 */
8805static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
8806 struct proxy *defpx, const char *file, int line,
8807 char **err)
8808{
8809 int *target;
8810
8811 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
8812 target = &global.tune.sslcachesize;
8813 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008814 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008815 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01008816 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01008817 else if (strcmp(args[0], "maxsslconn") == 0)
8818 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008819 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
8820 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008821 else {
8822 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
8823 return -1;
8824 }
8825
8826 if (too_many_args(1, args, err, NULL))
8827 return -1;
8828
8829 if (*(args[1]) == 0) {
8830 memprintf(err, "'%s' expects an integer argument.", args[0]);
8831 return -1;
8832 }
8833
8834 *target = atoi(args[1]);
8835 if (*target < 0) {
8836 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
8837 return -1;
8838 }
8839 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008840}
8841
8842static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
8843 struct proxy *defpx, const char *file, int line,
8844 char **err)
8845{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008846 int ret;
8847
8848 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
8849 if (ret != 0)
8850 return ret;
8851
Willy Tarreaubafbe012017-11-24 17:34:44 +01008852 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008853 memprintf(err, "'%s' is already configured.", args[0]);
8854 return -1;
8855 }
8856
Willy Tarreaubafbe012017-11-24 17:34:44 +01008857 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
8858 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01008859 memprintf(err, "Out of memory error.");
8860 return -1;
8861 }
8862 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008863}
8864
8865/* parse "ssl.force-private-cache".
8866 * Returns <0 on alert, >0 on warning, 0 on success.
8867 */
8868static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
8869 struct proxy *defpx, const char *file, int line,
8870 char **err)
8871{
8872 if (too_many_args(0, args, err, NULL))
8873 return -1;
8874
Willy Tarreauef934602016-12-22 23:12:01 +01008875 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01008876 return 0;
8877}
8878
8879/* parse "ssl.lifetime".
8880 * Returns <0 on alert, >0 on warning, 0 on success.
8881 */
8882static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
8883 struct proxy *defpx, const char *file, int line,
8884 char **err)
8885{
8886 const char *res;
8887
8888 if (too_many_args(1, args, err, NULL))
8889 return -1;
8890
8891 if (*(args[1]) == 0) {
8892 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
8893 return -1;
8894 }
8895
Willy Tarreauef934602016-12-22 23:12:01 +01008896 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9ceda382016-12-21 23:13:03 +01008897 if (res) {
8898 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
8899 return -1;
8900 }
8901 return 0;
8902}
8903
8904#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01008905/* parse "ssl-dh-param-file".
8906 * Returns <0 on alert, >0 on warning, 0 on success.
8907 */
8908static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
8909 struct proxy *defpx, const char *file, int line,
8910 char **err)
8911{
8912 if (too_many_args(1, args, err, NULL))
8913 return -1;
8914
8915 if (*(args[1]) == 0) {
8916 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
8917 return -1;
8918 }
8919
8920 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
8921 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
8922 return -1;
8923 }
8924 return 0;
8925}
8926
Willy Tarreau9ceda382016-12-21 23:13:03 +01008927/* parse "ssl.default-dh-param".
8928 * Returns <0 on alert, >0 on warning, 0 on success.
8929 */
8930static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
8931 struct proxy *defpx, const char *file, int line,
8932 char **err)
8933{
8934 if (too_many_args(1, args, err, NULL))
8935 return -1;
8936
8937 if (*(args[1]) == 0) {
8938 memprintf(err, "'%s' expects an integer argument.", args[0]);
8939 return -1;
8940 }
8941
Willy Tarreauef934602016-12-22 23:12:01 +01008942 global_ssl.default_dh_param = atoi(args[1]);
8943 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01008944 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
8945 return -1;
8946 }
8947 return 0;
8948}
8949#endif
8950
8951
William Lallemand32af2032016-10-29 18:09:35 +02008952/* This function is used with TLS ticket keys management. It permits to browse
8953 * each reference. The variable <getnext> must contain the current node,
8954 * <end> point to the root node.
8955 */
8956#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8957static inline
8958struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
8959{
8960 struct tls_keys_ref *ref = getnext;
8961
8962 while (1) {
8963
8964 /* Get next list entry. */
8965 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
8966
8967 /* If the entry is the last of the list, return NULL. */
8968 if (&ref->list == end)
8969 return NULL;
8970
8971 return ref;
8972 }
8973}
8974
8975static inline
8976struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
8977{
8978 int id;
8979 char *error;
8980
8981 /* If the reference starts by a '#', this is numeric id. */
8982 if (reference[0] == '#') {
8983 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
8984 id = strtol(reference + 1, &error, 10);
8985 if (*error != '\0')
8986 return NULL;
8987
8988 /* Perform the unique id lookup. */
8989 return tlskeys_ref_lookupid(id);
8990 }
8991
8992 /* Perform the string lookup. */
8993 return tlskeys_ref_lookup(reference);
8994}
8995#endif
8996
8997
8998#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8999
9000static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9001
9002static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9003 return cli_io_handler_tlskeys_files(appctx);
9004}
9005
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009006/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9007 * (next index to be dumped), and cli.p0 (next key reference).
9008 */
William Lallemand32af2032016-10-29 18:09:35 +02009009static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9010
9011 struct stream_interface *si = appctx->owner;
9012
9013 switch (appctx->st2) {
9014 case STAT_ST_INIT:
9015 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009016 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009017 * later and restart at the state "STAT_ST_INIT".
9018 */
9019 chunk_reset(&trash);
9020
9021 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9022 chunk_appendf(&trash, "# id secret\n");
9023 else
9024 chunk_appendf(&trash, "# id (file)\n");
9025
Willy Tarreau06d80a92017-10-19 14:32:15 +02009026 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009027 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009028 return 0;
9029 }
9030
William Lallemand32af2032016-10-29 18:09:35 +02009031 /* Now, we start the browsing of the references lists.
9032 * Note that the following call to LIST_ELEM return bad pointer. The only
9033 * available field of this pointer is <list>. It is used with the function
9034 * tlskeys_list_get_next() for retruning the first available entry
9035 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009036 if (appctx->ctx.cli.p0 == NULL) {
9037 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9038 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009039 }
9040
9041 appctx->st2 = STAT_ST_LIST;
9042 /* fall through */
9043
9044 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009045 while (appctx->ctx.cli.p0) {
9046 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009047
9048 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009049 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009050 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009051
9052 if (appctx->ctx.cli.i1 == 0)
9053 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9054
William Lallemand32af2032016-10-29 18:09:35 +02009055 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009056 int head;
9057
9058 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9059 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009060 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009061 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009062
9063 chunk_reset(t2);
9064 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009065 if (ref->key_size_bits == 128) {
9066 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9067 sizeof(struct tls_sess_key_128),
9068 t2->area, t2->size);
9069 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9070 t2->area);
9071 }
9072 else if (ref->key_size_bits == 256) {
9073 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9074 sizeof(struct tls_sess_key_256),
9075 t2->area, t2->size);
9076 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9077 t2->area);
9078 }
9079 else {
9080 /* This case should never happen */
9081 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9082 }
William Lallemand32af2032016-10-29 18:09:35 +02009083
Willy Tarreau06d80a92017-10-19 14:32:15 +02009084 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009085 /* let's try again later from this stream. We add ourselves into
9086 * this stream's users so that it can remove us upon termination.
9087 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009088 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009089 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009090 return 0;
9091 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009092 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009093 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009094 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009095 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009096 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009097 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009098 /* let's try again later from this stream. We add ourselves into
9099 * this stream's users so that it can remove us upon termination.
9100 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009101 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009102 return 0;
9103 }
9104
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009105 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009106 break;
9107
9108 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009109 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009110 }
9111
9112 appctx->st2 = STAT_ST_FIN;
9113 /* fall through */
9114
9115 default:
9116 appctx->st2 = STAT_ST_FIN;
9117 return 1;
9118 }
9119 return 0;
9120}
9121
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009122/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009123static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009124{
William Lallemand32af2032016-10-29 18:09:35 +02009125 /* no parameter, shows only file list */
9126 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009127 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009128 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009129 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009130 }
9131
9132 if (args[2][0] == '*') {
9133 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009134 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009135 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009136 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
9137 if (!appctx->ctx.cli.p0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009138 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009139 appctx->ctx.cli.msg = "'show tls-keys' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009140 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009141 return 1;
9142 }
9143 }
William Lallemand32af2032016-10-29 18:09:35 +02009144 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009145 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009146}
9147
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009148static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009149{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009150 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009151 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009152
William Lallemand32af2032016-10-29 18:09:35 +02009153 /* Expect two parameters: the filename and the new new TLS key in encoding */
9154 if (!*args[3] || !*args[4]) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009155 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009156 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 +01009157 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009158 return 1;
9159 }
9160
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009161 ref = tlskeys_ref_lookup_ref(args[3]);
9162 if (!ref) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009163 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009164 appctx->ctx.cli.msg = "'set ssl tls-key' unable to locate referenced filename\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009165 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009166 return 1;
9167 }
9168
Willy Tarreau1c913e42018-08-22 05:26:57 +02009169 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Emeric Brun9e754772019-01-10 17:51:55 +01009170 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009171 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009172 appctx->ctx.cli.msg = "'set ssl tls-key' received invalid base64 encoded TLS key.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009173 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009174 return 1;
9175 }
Emeric Brun9e754772019-01-10 17:51:55 +01009176
Willy Tarreau1c913e42018-08-22 05:26:57 +02009177 trash.data = ret;
Emeric Brun9e754772019-01-10 17:51:55 +01009178 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0) {
9179 appctx->ctx.cli.severity = LOG_ERR;
9180 appctx->ctx.cli.msg = "'set ssl tls-key' received a key of wrong size.\n";
9181 appctx->st0 = CLI_ST_PRINT;
9182 return 1;
9183 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009184 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009185 appctx->ctx.cli.msg = "TLS ticket key updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009186 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009187 return 1;
9188
9189}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009190#endif
William Lallemand32af2032016-10-29 18:09:35 +02009191
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009192static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009193{
9194#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9195 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009196 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009197
9198 if (!payload)
9199 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009200
9201 /* Expect one parameter: the new response in base64 encoding */
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009202 if (!*payload) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009203 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009204 appctx->ctx.cli.msg = "'set ssl ocsp-response' expects response in base64 encoding.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009205 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009206 return 1;
9207 }
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009208
9209 /* remove \r and \n from the payload */
9210 for (i = 0, j = 0; payload[i]; i++) {
9211 if (payload[i] == '\r' || payload[i] == '\n')
9212 continue;
9213 payload[j++] = payload[i];
9214 }
9215 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009216
Willy Tarreau1c913e42018-08-22 05:26:57 +02009217 ret = base64dec(payload, j, trash.area, trash.size);
9218 if (ret < 0) {
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009219 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009220 appctx->ctx.cli.msg = "'set ssl ocsp-response' received invalid base64 encoded response.\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009221 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009222 return 1;
9223 }
9224
Willy Tarreau1c913e42018-08-22 05:26:57 +02009225 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009226 if (ssl_sock_update_ocsp_response(&trash, &err)) {
9227 if (err) {
9228 memprintf(&err, "%s.\n", err);
9229 appctx->ctx.cli.err = err;
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009230 appctx->st0 = CLI_ST_PRINT_FREE;
William Lallemand32af2032016-10-29 18:09:35 +02009231 }
Aurélien Nephtali9a4da682018-04-16 19:02:42 +02009232 else {
9233 appctx->ctx.cli.severity = LOG_ERR;
9234 appctx->ctx.cli.msg = "Failed to update OCSP response.\n";
9235 appctx->st0 = CLI_ST_PRINT;
9236 }
William Lallemand32af2032016-10-29 18:09:35 +02009237 return 1;
9238 }
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009239 appctx->ctx.cli.severity = LOG_INFO;
Aurélien Nephtali6e8a41d2018-03-15 21:48:50 +01009240 appctx->ctx.cli.msg = "OCSP Response updated!\n";
Willy Tarreau3b6e5472016-11-24 15:53:53 +01009241 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009242 return 1;
9243#else
Andjelko Iharosc3680ec2017-07-20 16:49:14 +02009244 appctx->ctx.cli.severity = LOG_ERR;
William Lallemand32af2032016-10-29 18:09:35 +02009245 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 +01009246 appctx->st0 = CLI_ST_PRINT;
William Lallemand32af2032016-10-29 18:09:35 +02009247 return 1;
9248#endif
9249
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009250}
9251
Willy Tarreau86a394e2019-05-09 14:15:32 +02009252#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009253static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9254{
9255 switch (arg->type) {
9256 case ARGT_STR:
9257 smp->data.type = SMP_T_STR;
9258 smp->data.u.str = arg->data.str;
9259 return 1;
9260 case ARGT_VAR:
9261 if (!vars_get_by_desc(&arg->data.var, smp))
9262 return 0;
9263 if (!sample_casts[smp->data.type][SMP_T_STR])
9264 return 0;
9265 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9266 return 0;
9267 return 1;
9268 default:
9269 return 0;
9270 }
9271}
9272
9273static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9274 const char *file, int line, char **err)
9275{
9276 switch(args[0].data.sint) {
9277 case 128:
9278 case 192:
9279 case 256:
9280 break;
9281 default:
9282 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9283 return 0;
9284 }
9285 /* Try to decode a variable. */
9286 vars_check_arg(&args[1], NULL);
9287 vars_check_arg(&args[2], NULL);
9288 vars_check_arg(&args[3], NULL);
9289 return 1;
9290}
9291
9292/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9293static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9294{
9295 struct sample nonce, key, aead_tag;
9296 struct buffer *smp_trash, *smp_trash_alloc;
9297 EVP_CIPHER_CTX *ctx;
9298 int dec_size, ret;
9299
9300 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9301 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9302 return 0;
9303
9304 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9305 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9306 return 0;
9307
9308 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9309 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9310 return 0;
9311
9312 smp_trash = get_trash_chunk();
9313 smp_trash_alloc = alloc_trash_chunk();
9314 if (!smp_trash_alloc)
9315 return 0;
9316
9317 ctx = EVP_CIPHER_CTX_new();
9318
9319 if (!ctx)
9320 goto err;
9321
9322 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9323 if (dec_size < 0)
9324 goto err;
9325 smp_trash->data = dec_size;
9326
9327 /* Set cipher type and mode */
9328 switch(arg_p[0].data.sint) {
9329 case 128:
9330 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9331 break;
9332 case 192:
9333 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9334 break;
9335 case 256:
9336 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9337 break;
9338 }
9339
9340 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9341
9342 /* Initialise IV */
9343 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9344 goto err;
9345
9346 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9347 if (dec_size < 0)
9348 goto err;
9349 smp_trash->data = dec_size;
9350
9351 /* Initialise key */
9352 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9353 goto err;
9354
9355 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9356 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9357 goto err;
9358
9359 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9360 if (dec_size < 0)
9361 goto err;
9362 smp_trash_alloc->data = dec_size;
9363 dec_size = smp_trash->data;
9364
9365 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9366 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9367
9368 if (ret <= 0)
9369 goto err;
9370
9371 smp->data.u.str.data = dec_size + smp_trash->data;
9372 smp->data.u.str.area = smp_trash->area;
9373 smp->data.type = SMP_T_BIN;
9374 smp->flags &= ~SMP_F_CONST;
9375 free_trash_chunk(smp_trash_alloc);
9376 return 1;
9377
9378err:
9379 free_trash_chunk(smp_trash_alloc);
9380 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009381}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009382# endif
William Lallemand32af2032016-10-29 18:09:35 +02009383
9384/* register cli keywords */
9385static struct cli_kw_list cli_kws = {{ },{
9386#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9387 { { "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 +02009388 { { "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 +02009389#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009390 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009391 { { NULL }, NULL, NULL, NULL }
9392}};
9393
Willy Tarreau0108d902018-11-25 19:14:37 +01009394INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009395
Willy Tarreau7875d092012-09-10 08:20:03 +02009396/* Note: must not be declared <const> as its list will be overwritten.
9397 * Please take care of keeping this list alphabetically sorted.
9398 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009399static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009400 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009401 { "ssl_bc_alg_keysize", smp_fetch_ssl_fc_alg_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009402#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009403 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009404#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009405 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009406#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9407 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9408#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009409 { "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 +02009410 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009411 { "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 +02009412 { "ssl_bc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009413#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009414 { "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 -04009415#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009416#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
Patrick Hemmere0275472018-04-28 19:15:51 -04009417 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9418#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009419 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9420 { "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 +01009421 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009422 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009423 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9424 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9425 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9426 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9427 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9428 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9429 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9430 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009431 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009432 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9433 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009434 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009435 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9436 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9437 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9438 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9439 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9440 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9441 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009442 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009443 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009444 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009445 { "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 +01009446 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009447 { "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 +02009448 { "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 +01009449 { "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 +02009450 { "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 +01009451#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009452 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009453#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009454#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009455 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009456#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009457 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009458#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009459 { "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 -04009460#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009461 { "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009462#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009463 { "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 -04009464#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009465#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL)
Patrick Hemmere0275472018-04-28 19:15:51 -04009466 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9467#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009468#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009469 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009470#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009471 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9472 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9473 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9474 { "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 +02009475 { NULL, NULL, 0, 0, 0 },
9476}};
9477
Willy Tarreau0108d902018-11-25 19:14:37 +01009478INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9479
Willy Tarreau7875d092012-09-10 08:20:03 +02009480/* Note: must not be declared <const> as its list will be overwritten.
9481 * Please take care of keeping this list alphabetically sorted.
9482 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009483static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +01009484 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
9485 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +01009486 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +02009487}};
9488
Willy Tarreau0108d902018-11-25 19:14:37 +01009489INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
9490
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009491/* Note: must not be declared <const> as its list will be overwritten.
9492 * Please take care of keeping this list alphabetically sorted, doing so helps
9493 * all code contributors.
9494 * Optional keywords are also declared with a NULL ->parse() function so that
9495 * the config parser can report an appropriate error when a known keyword was
9496 * not enabled.
9497 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009498static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009499 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009500 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9501 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9502 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Willy Tarreau5db847a2019-05-09 14:13:35 +02009503#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009504 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9505#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009506 { "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 +01009507 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009508 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009509 { "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 +01009510 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02009511 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
9512 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01009513 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
9514 { NULL, NULL, 0 },
9515};
9516
Willy Tarreau0108d902018-11-25 19:14:37 +01009517/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
9518
Willy Tarreau51fb7652012-09-18 18:24:39 +02009519static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +02009520 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009521 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
9522 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
9523 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
9524 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
9525 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
9526 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Willy Tarreau5db847a2019-05-09 14:13:35 +02009527#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009528 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
9529#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009530 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
9531 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
9532 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
9533 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
9534 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
9535 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
9536 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
9537 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
9538 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
9539 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009540 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009541 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02009542 { "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 +02009543 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
9544 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
9545 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
9546 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02009547 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009548 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
9549 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009550 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
9551 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009552 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
9553 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
9554 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
9555 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
9556 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +02009557 { NULL, NULL, 0 },
9558}};
Emeric Brun46591952012-05-18 15:47:34 +02009559
Willy Tarreau0108d902018-11-25 19:14:37 +01009560INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
9561
Willy Tarreau92faadf2012-10-10 23:04:25 +02009562/* Note: must not be declared <const> as its list will be overwritten.
9563 * Please take care of keeping this list alphabetically sorted, doing so helps
9564 * all code contributors.
9565 * Optional keywords are also declared with a NULL ->parse() function so that
9566 * the config parser can report an appropriate error when a known keyword was
9567 * not enabled.
9568 */
9569static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +01009570 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +01009571 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009572 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +01009573 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +02009574 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009575 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
9576 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Willy Tarreau5db847a2019-05-09 14:13:35 +02009577#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009578 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
9579#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009580 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
9581 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
9582 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
9583 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
9584 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
9585 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
9586 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
9587 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
9588 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
9589 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
9590 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
9591 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
9592 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
9593 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
9594 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
9595 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
9596 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
9597 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +01009598 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009599 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
9600 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
9601 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
9602 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
9603 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
9604 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
9605 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
9606 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
9607 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
9608 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +02009609 { NULL, NULL, 0, 0 },
9610}};
9611
Willy Tarreau0108d902018-11-25 19:14:37 +01009612INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
9613
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009614static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009615 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
9616 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009617 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009618 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
9619 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +01009620#ifndef OPENSSL_NO_DH
9621 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
9622#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009623 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009624#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009625 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009626#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +01009627 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
9628#ifndef OPENSSL_NO_DH
9629 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
9630#endif
9631 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
9632 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
9633 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
9634 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009635 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +01009636 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
9637 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Willy Tarreau5db847a2019-05-09 14:13:35 +02009638#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009639 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
9640 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
9641#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009642 { 0, NULL, NULL },
9643}};
9644
Willy Tarreau0108d902018-11-25 19:14:37 +01009645INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
9646
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009647/* Note: must not be declared <const> as its list will be overwritten */
9648static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +02009649#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009650 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
9651#endif
9652 { NULL, NULL, 0, 0, 0 },
9653}};
9654
9655INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
9656
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02009657/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +01009658static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +02009659 .snd_buf = ssl_sock_from_buf,
9660 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +01009661 .subscribe = ssl_subscribe,
9662 .unsubscribe = ssl_unsubscribe,
Emeric Brun46591952012-05-18 15:47:34 +02009663 .rcv_pipe = NULL,
9664 .snd_pipe = NULL,
9665 .shutr = NULL,
9666 .shutw = ssl_sock_shutw,
9667 .close = ssl_sock_close,
9668 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +01009669 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +01009670 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +01009671 .prepare_srv = ssl_sock_prepare_srv_ctx,
9672 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +01009673 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +01009674 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +02009675};
9676
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009677enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
9678 struct session *sess, struct stream *s, int flags)
9679{
9680 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009681 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009682
9683 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009684 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009685
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009686 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009687 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +01009688 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +02009689 s->req.flags |= CF_READ_NULL;
9690 return ACT_RET_YIELD;
9691 }
9692 }
9693 return (ACT_RET_CONT);
9694}
9695
9696static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
9697{
9698 rule->action_ptr = ssl_action_wait_for_hs;
9699
9700 return ACT_RET_PRS_OK;
9701}
9702
9703static struct action_kw_list http_req_actions = {ILH, {
9704 { "wait-for-handshake", ssl_parse_wait_for_hs },
9705 { /* END */ }
9706}};
9707
Willy Tarreau0108d902018-11-25 19:14:37 +01009708INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
9709
Willy Tarreau5db847a2019-05-09 14:13:35 +02009710#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009711
9712static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9713{
9714 if (ptr) {
9715 chunk_destroy(ptr);
9716 free(ptr);
9717 }
9718}
9719
9720#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009721static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
9722{
Willy Tarreaubafbe012017-11-24 17:34:44 +01009723 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +01009724}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009725
Emeric Brun46591952012-05-18 15:47:34 +02009726__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +02009727static void __ssl_sock_init(void)
9728{
Emeric Brun46591952012-05-18 15:47:34 +02009729 STACK_OF(SSL_COMP)* cm;
9730
Willy Tarreauef934602016-12-22 23:12:01 +01009731 if (global_ssl.listen_default_ciphers)
9732 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
9733 if (global_ssl.connect_default_ciphers)
9734 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Willy Tarreau5db847a2019-05-09 14:13:35 +02009735#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined OPENSSL_IS_BORINGSSL)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009736 if (global_ssl.listen_default_ciphersuites)
9737 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
9738 if (global_ssl.connect_default_ciphersuites)
9739 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
9740#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +01009741
Willy Tarreau13e14102016-12-22 20:25:26 +01009742 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009743#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +02009744 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -08009745#endif
Emeric Brun46591952012-05-18 15:47:34 +02009746 cm = SSL_COMP_get_compression_methods();
9747 sk_SSL_COMP_zero(cm);
Willy Tarreau5db847a2019-05-09 14:13:35 +02009748#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009749 ssl_locking_init();
9750#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +02009751#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01009752 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
9753#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +02009754 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +02009755 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 +01009756 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009757#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009758 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009759 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009760#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +01009761#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9762 hap_register_post_check(tlskeys_finalize_config);
9763#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009764
9765 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
9766 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
9767
9768#ifndef OPENSSL_NO_DH
9769 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
9770 hap_register_post_deinit(ssl_free_dh);
9771#endif
9772#ifndef OPENSSL_NO_ENGINE
9773 hap_register_post_deinit(ssl_free_engines);
9774#endif
9775 /* Load SSL string for the verbose & debug mode. */
9776 ERR_load_SSL_strings();
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009777#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Olivier Houcharda8955d52019-04-07 22:00:38 +02009778 ha_meth = malloc(sizeof(*ha_meth));
Olivier Houchard66a7b332019-04-18 15:58:15 +02009779 bzero(ha_meth, sizeof(*ha_meth));
Olivier Houcharda8955d52019-04-07 22:00:38 +02009780 ha_meth->bwrite = ha_ssl_write;
9781 ha_meth->bread = ha_ssl_read;
9782 ha_meth->ctrl = ha_ssl_ctrl;
9783 ha_meth->create = ha_ssl_new;
9784 ha_meth->destroy = ha_ssl_free;
9785 ha_meth->bputs = ha_ssl_puts;
9786 ha_meth->bgets = ha_ssl_gets;
9787#else
9788 ha_meth = BIO_meth_new(0x666, "ha methods");
9789 BIO_meth_set_write(ha_meth, ha_ssl_write);
9790 BIO_meth_set_read(ha_meth, ha_ssl_read);
9791 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
9792 BIO_meth_set_create(ha_meth, ha_ssl_new);
9793 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
9794 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
9795 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
9796#endif
Willy Tarreau80713382018-11-26 10:19:54 +01009797}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +01009798
Willy Tarreau80713382018-11-26 10:19:54 +01009799/* Compute and register the version string */
9800static void ssl_register_build_options()
9801{
9802 char *ptr = NULL;
9803 int i;
9804
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009805 memprintf(&ptr, "Built with OpenSSL version : "
9806#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009807 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009808#else /* OPENSSL_IS_BORINGSSL */
9809 OPENSSL_VERSION_TEXT
9810 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -08009811 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +02009812 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009813#endif
9814 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009815#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009816 "no (library version too old)"
9817#elif defined(OPENSSL_NO_TLSEXT)
9818 "no (disabled via OPENSSL_NO_TLSEXT)"
9819#else
9820 "yes"
9821#endif
9822 "", ptr);
9823
9824 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
9825#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
9826 "yes"
9827#else
9828#ifdef OPENSSL_NO_TLSEXT
9829 "no (because of OPENSSL_NO_TLSEXT)"
9830#else
9831 "no (version might be too old, 0.9.8f min needed)"
9832#endif
9833#endif
9834 "", ptr);
9835
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +02009836 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
9837 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
9838 if (methodVersions[i].option)
9839 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +01009840
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009841 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +01009842}
Willy Tarreauc2c0b612016-12-21 19:23:20 +01009843
Willy Tarreau80713382018-11-26 10:19:54 +01009844INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +02009845
Emeric Brun46591952012-05-18 15:47:34 +02009846
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009847#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +00009848void ssl_free_engines(void) {
9849 struct ssl_engine_list *wl, *wlb;
9850 /* free up engine list */
9851 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
9852 ENGINE_finish(wl->e);
9853 ENGINE_free(wl->e);
9854 LIST_DEL(&wl->list);
9855 free(wl);
9856 }
9857}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009858#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +02009859
Remi Gacogned3a23c32015-05-28 16:39:47 +02009860#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +00009861void ssl_free_dh(void) {
9862 if (local_dh_1024) {
9863 DH_free(local_dh_1024);
9864 local_dh_1024 = NULL;
9865 }
9866 if (local_dh_2048) {
9867 DH_free(local_dh_2048);
9868 local_dh_2048 = NULL;
9869 }
9870 if (local_dh_4096) {
9871 DH_free(local_dh_4096);
9872 local_dh_4096 = NULL;
9873 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02009874 if (global_dh) {
9875 DH_free(global_dh);
9876 global_dh = NULL;
9877 }
Grant Zhang872f9c22017-01-21 01:10:18 +00009878}
9879#endif
9880
9881__attribute__((destructor))
9882static void __ssl_sock_deinit(void)
9883{
9884#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02009885 if (ssl_ctx_lru_tree) {
9886 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01009887 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +02009888 }
Remi Gacogned3a23c32015-05-28 16:39:47 +02009889#endif
9890
Willy Tarreau5db847a2019-05-09 14:13:35 +02009891#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009892 ERR_remove_state(0);
9893 ERR_free_strings();
9894
9895 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -08009896#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +02009897
Willy Tarreau5db847a2019-05-09 14:13:35 +02009898#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +02009899 CRYPTO_cleanup_all_ex_data();
9900#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009901#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Olivier Houcharda8955d52019-04-07 22:00:38 +02009902 free(ha_meth);
9903#else
9904 BIO_meth_free(ha_meth);
9905#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +02009906}
9907
9908
Emeric Brun46591952012-05-18 15:47:34 +02009909/*
9910 * Local variables:
9911 * c-indent-level: 8
9912 * c-basic-offset: 8
9913 * End:
9914 */