blob: 59191f2772ff32935a338792b5fba7424c07dbc6 [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>
Christopher Fauletfc9cfe42019-07-16 14:54:53 +020080#include <proto/http_ana.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;
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200160#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
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
Emmanuel Hocdet839af572019-05-14 16:27:35 +0200182#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
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 Houchard5149b592019-05-23 17:47:36 +0200214 const struct xprt_ops *xprt;
Olivier Houchard66ab4982019-02-26 18:37:15 +0100215 void *xprt_ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +0200216 struct wait_event wait_event;
217 struct wait_event *recv_wait;
218 struct wait_event *send_wait;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +0100219 int xprt_st; /* transport layer state, initialized to zero */
220 int tmp_early_data; /* 1st byte of early data, if any */
221 int sent_early_data; /* Amount of early data we sent so far */
222
Olivier Houchard66ab4982019-02-26 18:37:15 +0100223};
224
225DECLARE_STATIC_POOL(ssl_sock_ctx_pool, "ssl_sock_ctx_pool", sizeof(struct ssl_sock_ctx));
226
Olivier Houchardea8dd942019-05-20 14:02:16 +0200227static struct task *ssl_sock_io_cb(struct task *, void *, unsigned short);
Olivier Houchard000694c2019-05-23 14:45:12 +0200228static int ssl_sock_handshake(struct connection *conn, unsigned int flag);
Olivier Houchardea8dd942019-05-20 14:02:16 +0200229
Olivier Houcharda8955d52019-04-07 22:00:38 +0200230/* Methods to implement OpenSSL BIO */
231static int ha_ssl_write(BIO *h, const char *buf, int num)
232{
233 struct buffer tmpbuf;
234 struct ssl_sock_ctx *ctx;
235 int ret;
236
237 ctx = BIO_get_data(h);
238 tmpbuf.size = num;
239 tmpbuf.area = (void *)(uintptr_t)buf;
240 tmpbuf.data = num;
241 tmpbuf.head = 0;
242 ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200243 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200244 BIO_set_retry_write(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200245 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200246 } else if (ret == 0)
247 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200248 return ret;
249}
250
251static int ha_ssl_gets(BIO *h, char *buf, int size)
252{
253
254 return 0;
255}
256
257static int ha_ssl_puts(BIO *h, const char *str)
258{
259
260 return ha_ssl_write(h, str, strlen(str));
261}
262
263static int ha_ssl_read(BIO *h, char *buf, int size)
264{
265 struct buffer tmpbuf;
266 struct ssl_sock_ctx *ctx;
267 int ret;
268
269 ctx = BIO_get_data(h);
270 tmpbuf.size = size;
271 tmpbuf.area = buf;
272 tmpbuf.data = 0;
273 tmpbuf.head = 0;
274 ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
Olivier Houchardb51937e2019-05-01 17:24:36 +0200275 if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
Olivier Houcharda8955d52019-04-07 22:00:38 +0200276 BIO_set_retry_read(h);
Olivier Houcharda28454e2019-04-24 12:04:36 +0200277 ret = -1;
Olivier Houchardb51937e2019-05-01 17:24:36 +0200278 } else if (ret == 0)
279 BIO_clear_retry_flags(h);
Olivier Houcharda8955d52019-04-07 22:00:38 +0200280
281 return ret;
282}
283
284static long ha_ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2)
285{
286 int ret = 0;
287 switch (cmd) {
288 case BIO_CTRL_DUP:
289 case BIO_CTRL_FLUSH:
290 ret = 1;
291 break;
292 }
293 return ret;
294}
295
296static int ha_ssl_new(BIO *h)
297{
298 BIO_set_init(h, 1);
299 BIO_set_data(h, NULL);
300 BIO_clear_flags(h, ~0);
301 return 1;
302}
303
304static int ha_ssl_free(BIO *data)
305{
306
307 return 1;
308}
309
310
Willy Tarreau5db847a2019-05-09 14:13:35 +0200311#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100312
Emeric Brun821bb9b2017-06-15 16:37:39 +0200313static HA_RWLOCK_T *ssl_rwlocks;
314
315
316unsigned long ssl_id_function(void)
317{
318 return (unsigned long)tid;
319}
320
321void ssl_locking_function(int mode, int n, const char * file, int line)
322{
323 if (mode & CRYPTO_LOCK) {
324 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100325 HA_RWLOCK_RDLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200326 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100327 HA_RWLOCK_WRLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200328 }
329 else {
330 if (mode & CRYPTO_READ)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100331 HA_RWLOCK_RDUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200332 else
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100333 HA_RWLOCK_WRUNLOCK(SSL_LOCK, &ssl_rwlocks[n]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200334 }
335}
336
337static int ssl_locking_init(void)
338{
339 int i;
340
341 ssl_rwlocks = malloc(sizeof(HA_RWLOCK_T)*CRYPTO_num_locks());
342 if (!ssl_rwlocks)
343 return -1;
344
345 for (i = 0 ; i < CRYPTO_num_locks() ; i++)
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100346 HA_RWLOCK_INIT(&ssl_rwlocks[i]);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200347
348 CRYPTO_set_id_callback(ssl_id_function);
349 CRYPTO_set_locking_callback(ssl_locking_function);
350
351 return 0;
352}
Christopher Faulet9dcf9b62017-11-13 10:34:01 +0100353
Emeric Brun821bb9b2017-06-15 16:37:39 +0200354#endif
355
William Lallemand150bfa82019-09-19 17:12:49 +0200356__decl_hathreads(HA_SPINLOCK_T ckch_lock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200357
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100358/* This memory pool is used for capturing clienthello parameters. */
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100359struct ssl_capture {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +0100360 unsigned long long int xxh64;
361 unsigned char ciphersuite_len;
362 char ciphersuite[0];
363};
Willy Tarreaubafbe012017-11-24 17:34:44 +0100364struct pool_head *pool_head_ssl_capture = NULL;
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +0100365static int ssl_capture_ptr_index = -1;
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200366static int ssl_app_data_index = -1;
Willy Tarreauef934602016-12-22 23:12:01 +0100367
Emmanuel Hocdet96b78342017-10-31 15:46:07 +0100368static int ssl_pkey_info_index = -1;
369
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200370#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
371struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
372#endif
373
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200374#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000375static unsigned int openssl_engines_initialized;
376struct list openssl_engines = LIST_HEAD_INIT(openssl_engines);
377struct ssl_engine_list {
378 struct list list;
379 ENGINE *e;
380};
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200381#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000382
Remi Gacogne8de54152014-07-15 11:36:40 +0200383#ifndef OPENSSL_NO_DH
Remi Gacogne4f902b82015-05-28 16:23:00 +0200384static int ssl_dh_ptr_index = -1;
Remi Gacogne47783ef2015-05-29 15:53:22 +0200385static DH *global_dh = NULL;
Remi Gacogne8de54152014-07-15 11:36:40 +0200386static DH *local_dh_1024 = NULL;
387static DH *local_dh_2048 = NULL;
388static DH *local_dh_4096 = NULL;
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +0100389static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen);
Remi Gacogne8de54152014-07-15 11:36:40 +0200390#endif /* OPENSSL_NO_DH */
391
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100392#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +0200393/* X509V3 Extensions that will be added on generated certificates */
394#define X509V3_EXT_SIZE 5
395static char *x509v3_ext_names[X509V3_EXT_SIZE] = {
396 "basicConstraints",
397 "nsComment",
398 "subjectKeyIdentifier",
399 "authorityKeyIdentifier",
400 "keyUsage",
401};
402static char *x509v3_ext_values[X509V3_EXT_SIZE] = {
403 "CA:FALSE",
404 "\"OpenSSL Generated Certificate\"",
405 "hash",
406 "keyid,issuer:always",
407 "nonRepudiation,digitalSignature,keyEncipherment"
408};
Christopher Faulet31af49d2015-06-09 17:29:50 +0200409/* LRU cache to store generated certificate */
410static struct lru64_head *ssl_ctx_lru_tree = NULL;
411static unsigned int ssl_ctx_lru_seed = 0;
Emeric Brun821bb9b2017-06-15 16:37:39 +0200412static unsigned int ssl_ctx_serial;
Willy Tarreau86abe442018-11-25 20:12:18 +0100413__decl_rwlock(ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +0200414
Willy Tarreauc8ad3be2015-06-17 15:48:26 +0200415#endif // SSL_CTRL_SET_TLSEXT_HOSTNAME
416
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100417static struct ssl_bind_kw ssl_bind_kws[];
418
Willy Tarreau9a1ab082019-05-09 13:26:41 +0200419#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhube2774d2015-12-10 15:07:30 -0500420/* The order here matters for picking a default context,
421 * keep the most common keytype at the bottom of the list
422 */
423const char *SSL_SOCK_KEYTYPE_NAMES[] = {
424 "dsa",
425 "ecdsa",
426 "rsa"
427};
428#define SSL_SOCK_NUM_KEYTYPES 3
Willy Tarreau30da7ad2015-12-14 11:28:33 +0100429#else
430#define SSL_SOCK_NUM_KEYTYPES 1
yanbzhube2774d2015-12-10 15:07:30 -0500431#endif
432
William Lallemandc3cd35f2017-11-28 11:04:43 +0100433static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
William Lallemand4f45bb92017-10-30 20:08:51 +0100434static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
435
436#define sh_ssl_sess_tree_delete(s) ebmb_delete(&(s)->key);
437
438#define sh_ssl_sess_tree_insert(s) (struct sh_ssl_sess_hdr *)ebmb_insert(sh_ssl_sess_tree, \
439 &(s)->key, SSL_MAX_SSL_SESSION_ID_LENGTH);
440
441#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
442 (k), SSL_MAX_SSL_SESSION_ID_LENGTH);
William Lallemand3f85c9a2017-10-09 16:30:50 +0200443
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100444/*
445 * This function gives the detail of the SSL error. It is used only
446 * if the debug mode and the verbose mode are activated. It dump all
447 * the SSL error until the stack was empty.
448 */
449static forceinline void ssl_sock_dump_errors(struct connection *conn)
450{
451 unsigned long ret;
452
453 if (unlikely(global.mode & MODE_DEBUG)) {
454 while(1) {
455 ret = ERR_get_error();
456 if (ret == 0)
457 return;
458 fprintf(stderr, "fd[%04x] OpenSSL error[0x%lx] %s: %s\n",
Willy Tarreau585744b2017-08-24 14:31:19 +0200459 (unsigned short)conn->handle.fd, ret,
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100460 ERR_func_error_string(ret), ERR_reason_error_string(ret));
461 }
462 }
463}
464
yanbzhube2774d2015-12-10 15:07:30 -0500465
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200466#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +0000467static int ssl_init_single_engine(const char *engine_id, const char *def_algorithms)
468{
469 int err_code = ERR_ABORT;
470 ENGINE *engine;
471 struct ssl_engine_list *el;
472
473 /* grab the structural reference to the engine */
474 engine = ENGINE_by_id(engine_id);
475 if (engine == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100476 ha_alert("ssl-engine %s: failed to get structural reference\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000477 goto fail_get;
478 }
479
480 if (!ENGINE_init(engine)) {
481 /* the engine couldn't initialise, release it */
Christopher Faulet767a84b2017-11-24 16:50:31 +0100482 ha_alert("ssl-engine %s: failed to initialize\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000483 goto fail_init;
484 }
485
486 if (ENGINE_set_default_string(engine, def_algorithms) == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100487 ha_alert("ssl-engine %s: failed on ENGINE_set_default_string\n", engine_id);
Grant Zhang872f9c22017-01-21 01:10:18 +0000488 goto fail_set_method;
489 }
490
491 el = calloc(1, sizeof(*el));
492 el->e = engine;
493 LIST_ADD(&openssl_engines, &el->list);
Emeric Brunece0c332017-12-06 13:51:49 +0100494 nb_engines++;
495 if (global_ssl.async)
496 global.ssl_used_async_engines = nb_engines;
Grant Zhang872f9c22017-01-21 01:10:18 +0000497 return 0;
498
499fail_set_method:
500 /* release the functional reference from ENGINE_init() */
501 ENGINE_finish(engine);
502
503fail_init:
504 /* release the structural reference from ENGINE_by_id() */
505 ENGINE_free(engine);
506
507fail_get:
508 return err_code;
509}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +0200510#endif
Grant Zhang872f9c22017-01-21 01:10:18 +0000511
Willy Tarreau5db847a2019-05-09 14:13:35 +0200512#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +0200513/*
514 * openssl async fd handler
515 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200516void ssl_async_fd_handler(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000517{
Olivier Houchardea8dd942019-05-20 14:02:16 +0200518 struct ssl_sock_ctx *ctx = fdtab[fd].owner;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000519
Emeric Brun3854e012017-05-17 20:42:48 +0200520 /* fd is an async enfine fd, we must stop
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000521 * to poll this fd until it is requested
522 */
Emeric Brunbbc16542017-06-02 15:54:06 +0000523 fd_stop_recv(fd);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000524 fd_cant_recv(fd);
525
526 /* crypto engine is available, let's notify the associated
527 * connection that it can pursue its processing.
528 */
Olivier Houchard03abf2d2019-05-28 10:12:02 +0200529 ssl_sock_io_cb(NULL, ctx, 0);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000530}
531
Emeric Brun3854e012017-05-17 20:42:48 +0200532/*
533 * openssl async delayed SSL_free handler
534 */
Emeric Brund0e095c2019-04-19 17:15:28 +0200535void ssl_async_fd_free(int fd)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000536{
537 SSL *ssl = fdtab[fd].owner;
Emeric Brun3854e012017-05-17 20:42:48 +0200538 OSSL_ASYNC_FD all_fd[32];
539 size_t num_all_fds = 0;
540 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000541
Emeric Brun3854e012017-05-17 20:42:48 +0200542 /* We suppose that the async job for a same SSL *
543 * are serialized. So if we are awake it is
544 * because the running job has just finished
545 * and we can remove all async fds safely
546 */
547 SSL_get_all_async_fds(ssl, NULL, &num_all_fds);
548 if (num_all_fds > 32) {
549 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
550 return;
551 }
552
553 SSL_get_all_async_fds(ssl, all_fd, &num_all_fds);
554 for (i=0 ; i < num_all_fds ; i++)
555 fd_remove(all_fd[i]);
556
557 /* Now we can safely call SSL_free, no more pending job in engines */
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000558 SSL_free(ssl);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +0100559 _HA_ATOMIC_SUB(&sslconns, 1);
560 _HA_ATOMIC_SUB(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000561}
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000562/*
Emeric Brun3854e012017-05-17 20:42:48 +0200563 * function used to manage a returned SSL_ERROR_WANT_ASYNC
564 * and enable/disable polling for async fds
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000565 */
Olivier Houchardea8dd942019-05-20 14:02:16 +0200566static inline void ssl_async_process_fds(struct ssl_sock_ctx *ctx)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000567{
Willy Tarreaua9786b62018-01-25 07:22:13 +0100568 OSSL_ASYNC_FD add_fd[32];
Emeric Brun3854e012017-05-17 20:42:48 +0200569 OSSL_ASYNC_FD del_fd[32];
Olivier Houchardea8dd942019-05-20 14:02:16 +0200570 SSL *ssl = ctx->ssl;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000571 size_t num_add_fds = 0;
572 size_t num_del_fds = 0;
Emeric Brun3854e012017-05-17 20:42:48 +0200573 int i;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000574
575 SSL_get_changed_async_fds(ssl, NULL, &num_add_fds, NULL,
576 &num_del_fds);
Emeric Brun3854e012017-05-17 20:42:48 +0200577 if (num_add_fds > 32 || num_del_fds > 32) {
578 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 +0000579 return;
580 }
581
Emeric Brun3854e012017-05-17 20:42:48 +0200582 SSL_get_changed_async_fds(ssl, add_fd, &num_add_fds, del_fd, &num_del_fds);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000583
Emeric Brun3854e012017-05-17 20:42:48 +0200584 /* We remove unused fds from the fdtab */
585 for (i=0 ; i < num_del_fds ; i++)
586 fd_remove(del_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000587
Emeric Brun3854e012017-05-17 20:42:48 +0200588 /* We add new fds to the fdtab */
589 for (i=0 ; i < num_add_fds ; i++) {
Olivier Houchardea8dd942019-05-20 14:02:16 +0200590 fd_insert(add_fd[i], ctx, ssl_async_fd_handler, tid_bit);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000591 }
592
Emeric Brun3854e012017-05-17 20:42:48 +0200593 num_add_fds = 0;
594 SSL_get_all_async_fds(ssl, NULL, &num_add_fds);
595 if (num_add_fds > 32) {
596 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
597 return;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000598 }
Emeric Brun3854e012017-05-17 20:42:48 +0200599
600 /* We activate the polling for all known async fds */
601 SSL_get_all_async_fds(ssl, add_fd, &num_add_fds);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000602 for (i=0 ; i < num_add_fds ; i++) {
Emeric Brun3854e012017-05-17 20:42:48 +0200603 fd_want_recv(add_fd[i]);
Emeric Brunce9e01c2017-05-31 10:02:53 +0000604 /* To ensure that the fd cache won't be used
605 * We'll prefer to catch a real RD event
606 * because handling an EAGAIN on this fd will
607 * result in a context switch and also
608 * some engines uses a fd in blocking mode.
609 */
610 fd_cant_recv(add_fd[i]);
611 }
Emeric Brun3854e012017-05-17 20:42:48 +0200612
Grant Zhangfa6c7ee2017-01-14 01:42:15 +0000613}
614#endif
615
William Lallemand104a7a62019-10-14 14:14:59 +0200616#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200617/*
618 * This function returns the number of seconds elapsed
619 * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
620 * date presented un ASN1_GENERALIZEDTIME.
621 *
622 * In parsing error case, it returns -1.
623 */
624static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
625{
626 long epoch;
627 char *p, *end;
628 const unsigned short month_offset[12] = {
629 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
630 };
631 int year, month;
632
633 if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
634
635 p = (char *)d->data;
636 end = p + d->length;
637
638 if (end - p < 4) return -1;
639 year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
640 p += 4;
641 if (end - p < 2) return -1;
642 month = 10 * (p[0] - '0') + p[1] - '0';
643 if (month < 1 || month > 12) return -1;
644 /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
645 We consider leap years and the current month (<marsh or not) */
646 epoch = ( ((year - 1970) * 365)
647 + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
648 - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
649 + month_offset[month-1]
650 ) * 24 * 60 * 60;
651 p += 2;
652 if (end - p < 2) return -1;
653 /* Add the number of seconds of completed days of current month */
654 epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
655 p += 2;
656 if (end - p < 2) return -1;
657 /* Add the completed hours of the current day */
658 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
659 p += 2;
660 if (end - p < 2) return -1;
661 /* Add the completed minutes of the current hour */
662 epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
663 p += 2;
664 if (p == end) return -1;
665 /* Test if there is available seconds */
666 if (p[0] < '0' || p[0] > '9')
667 goto nosec;
668 if (end - p < 2) return -1;
669 /* Add the seconds of the current minute */
670 epoch += 10 * (p[0] - '0') + p[1] - '0';
671 p += 2;
672 if (p == end) return -1;
673 /* Ignore seconds float part if present */
674 if (p[0] == '.') {
675 do {
676 if (++p == end) return -1;
677 } while (p[0] >= '0' && p[0] <= '9');
678 }
679
680nosec:
681 if (p[0] == 'Z') {
682 if (end - p != 1) return -1;
683 return epoch;
684 }
685 else if (p[0] == '+') {
686 if (end - p != 5) return -1;
687 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700688 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 +0200689 }
690 else if (p[0] == '-') {
691 if (end - p != 5) return -1;
692 /* Apply timezone offset */
Frederik Deweerdt953917a2017-10-16 07:37:31 -0700693 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 +0200694 }
695
696 return -1;
697}
698
William Lallemand104a7a62019-10-14 14:14:59 +0200699/*
700 * struct alignment works here such that the key.key is the same as key_data
701 * Do not change the placement of key_data
702 */
703struct certificate_ocsp {
704 struct ebmb_node key;
705 unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
706 struct buffer response;
707 long expire;
708};
709
710struct ocsp_cbk_arg {
711 int is_single;
712 int single_kt;
713 union {
714 struct certificate_ocsp *s_ocsp;
715 /*
716 * m_ocsp will have multiple entries dependent on key type
717 * Entry 0 - DSA
718 * Entry 1 - ECDSA
719 * Entry 2 - RSA
720 */
721 struct certificate_ocsp *m_ocsp[SSL_SOCK_NUM_KEYTYPES];
722 };
723};
724
Emeric Brun1d3865b2014-06-20 15:37:32 +0200725static struct eb_root cert_ocsp_tree = EB_ROOT_UNIQUE;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200726
727/* This function starts to check if the OCSP response (in DER format) contained
728 * in chunk 'ocsp_response' is valid (else exits on error).
729 * If 'cid' is not NULL, it will be compared to the OCSP certificate ID
730 * contained in the OCSP Response and exits on error if no match.
731 * If it's a valid OCSP Response:
732 * If 'ocsp' is not NULL, the chunk is copied in the OCSP response's container
733 * pointed by 'ocsp'.
734 * If 'ocsp' is NULL, the function looks up into the OCSP response's
735 * containers tree (using as index the ASN1 form of the OCSP Certificate ID extracted
736 * from the response) and exits on error if not found. Finally, If an OCSP response is
737 * already present in the container, it will be overwritten.
738 *
739 * Note: OCSP response containing more than one OCSP Single response is not
740 * considered valid.
741 *
742 * Returns 0 on success, 1 in error case.
743 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200744static int ssl_sock_load_ocsp_response(struct buffer *ocsp_response,
745 struct certificate_ocsp *ocsp,
746 OCSP_CERTID *cid, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200747{
748 OCSP_RESPONSE *resp;
749 OCSP_BASICRESP *bs = NULL;
750 OCSP_SINGLERESP *sr;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200751 OCSP_CERTID *id;
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200752 unsigned char *p = (unsigned char *) ocsp_response->area;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200753 int rc , count_sr;
Emeric Brun13a6b482014-06-20 15:44:34 +0200754 ASN1_GENERALIZEDTIME *revtime, *thisupd, *nextupd = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200755 int reason;
756 int ret = 1;
757
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200758 resp = d2i_OCSP_RESPONSE(NULL, (const unsigned char **)&p,
759 ocsp_response->data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200760 if (!resp) {
761 memprintf(err, "Unable to parse OCSP response");
762 goto out;
763 }
764
765 rc = OCSP_response_status(resp);
766 if (rc != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
767 memprintf(err, "OCSP response status not successful");
768 goto out;
769 }
770
771 bs = OCSP_response_get1_basic(resp);
772 if (!bs) {
773 memprintf(err, "Failed to get basic response from OCSP Response");
774 goto out;
775 }
776
777 count_sr = OCSP_resp_count(bs);
778 if (count_sr > 1) {
779 memprintf(err, "OCSP response ignored because contains multiple single responses (%d)", count_sr);
780 goto out;
781 }
782
783 sr = OCSP_resp_get0(bs, 0);
784 if (!sr) {
785 memprintf(err, "Failed to get OCSP single response");
786 goto out;
787 }
788
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200789 id = (OCSP_CERTID*)OCSP_SINGLERESP_get0_id(sr);
790
Emeric Brun4147b2e2014-06-16 18:36:30 +0200791 rc = OCSP_single_get0_status(sr, &reason, &revtime, &thisupd, &nextupd);
Emmanuel Hocdetef607052017-10-24 14:57:16 +0200792 if (rc != V_OCSP_CERTSTATUS_GOOD && rc != V_OCSP_CERTSTATUS_REVOKED) {
Emmanuel Hocdet872085c2017-10-10 15:18:52 +0200793 memprintf(err, "OCSP single response: certificate status is unknown");
Emeric Brun4147b2e2014-06-16 18:36:30 +0200794 goto out;
795 }
796
Emeric Brun13a6b482014-06-20 15:44:34 +0200797 if (!nextupd) {
798 memprintf(err, "OCSP single response: missing nextupdate");
799 goto out;
800 }
801
Emeric Brunc8b27b62014-06-19 14:16:17 +0200802 rc = OCSP_check_validity(thisupd, nextupd, OCSP_MAX_RESPONSE_TIME_SKEW, -1);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200803 if (!rc) {
804 memprintf(err, "OCSP single response: no longer valid.");
805 goto out;
806 }
807
808 if (cid) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200809 if (OCSP_id_cmp(id, cid)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +0200810 memprintf(err, "OCSP single response: Certificate ID does not match certificate and issuer");
811 goto out;
812 }
813 }
814
815 if (!ocsp) {
816 unsigned char key[OCSP_MAX_CERTID_ASN1_LENGTH];
817 unsigned char *p;
818
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200819 rc = i2d_OCSP_CERTID(id, NULL);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200820 if (!rc) {
821 memprintf(err, "OCSP single response: Unable to encode Certificate ID");
822 goto out;
823 }
824
825 if (rc > OCSP_MAX_CERTID_ASN1_LENGTH) {
826 memprintf(err, "OCSP single response: Certificate ID too long");
827 goto out;
828 }
829
830 p = key;
831 memset(key, 0, OCSP_MAX_CERTID_ASN1_LENGTH);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +0200832 i2d_OCSP_CERTID(id, &p);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200833 ocsp = (struct certificate_ocsp *)ebmb_lookup(&cert_ocsp_tree, key, OCSP_MAX_CERTID_ASN1_LENGTH);
834 if (!ocsp) {
835 memprintf(err, "OCSP single response: Certificate ID does not match any certificate or issuer");
836 goto out;
837 }
838 }
839
840 /* According to comments on "chunk_dup", the
841 previous chunk buffer will be freed */
842 if (!chunk_dup(&ocsp->response, ocsp_response)) {
843 memprintf(err, "OCSP response: Memory allocation error");
844 goto out;
845 }
846
Emeric Brun4f3c87a2014-06-20 15:46:13 +0200847 ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
848
Emeric Brun4147b2e2014-06-16 18:36:30 +0200849 ret = 0;
850out:
Janusz Dziemidowicz8d710492017-03-08 16:59:41 +0100851 ERR_clear_error();
852
Emeric Brun4147b2e2014-06-16 18:36:30 +0200853 if (bs)
854 OCSP_BASICRESP_free(bs);
855
856 if (resp)
857 OCSP_RESPONSE_free(resp);
858
859 return ret;
860}
861/*
862 * External function use to update the OCSP response in the OCSP response's
863 * containers tree. The chunk 'ocsp_response' must contain the OCSP response
864 * to update in DER format.
865 *
866 * Returns 0 on success, 1 in error case.
867 */
Willy Tarreau83061a82018-07-13 11:56:34 +0200868int ssl_sock_update_ocsp_response(struct buffer *ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200869{
870 return ssl_sock_load_ocsp_response(ocsp_response, NULL, NULL, err);
871}
872
William Lallemand4a660132019-10-14 14:51:41 +0200873#endif
874
875#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200876/*
877 * This function load the OCSP Resonse in DER format contained in file at
William Lallemand246c0242019-10-11 08:59:13 +0200878 * path 'ocsp_path'
Emeric Brun4147b2e2014-06-16 18:36:30 +0200879 *
880 * Returns 0 on success, 1 in error case.
881 */
William Lallemand246c0242019-10-11 08:59:13 +0200882static int ssl_sock_load_ocsp_response_from_file(const char *ocsp_path, struct buffer **ocsp_response, char **err)
Emeric Brun4147b2e2014-06-16 18:36:30 +0200883{
884 int fd = -1;
885 int r = 0;
886 int ret = 1;
887
888 fd = open(ocsp_path, O_RDONLY);
889 if (fd == -1) {
890 memprintf(err, "Error opening OCSP response file");
891 goto end;
892 }
893
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200894 trash.data = 0;
895 while (trash.data < trash.size) {
896 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +0200897 if (r < 0) {
898 if (errno == EINTR)
899 continue;
900
901 memprintf(err, "Error reading OCSP response from file");
902 goto end;
903 }
904 else if (r == 0) {
905 break;
906 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200907 trash.data += r;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200908 }
909
William Lallemand246c0242019-10-11 08:59:13 +0200910 *ocsp_response = calloc(1, sizeof(**ocsp_response));
911 if (!chunk_dup(*ocsp_response, &trash)) {
912 free(*ocsp_response);
913 *ocsp_response = NULL;
914 goto end;
915 }
916
Emeric Brun4147b2e2014-06-16 18:36:30 +0200917 close(fd);
918 fd = -1;
919
William Lallemande0f48ae2019-10-15 13:44:57 +0200920 ret = 0;
Emeric Brun4147b2e2014-06-16 18:36:30 +0200921end:
922 if (fd != -1)
923 close(fd);
924
925 return ret;
926}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +0100927#endif
Emeric Brun4147b2e2014-06-16 18:36:30 +0200928
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100929#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
930static 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)
931{
Christopher Faulet16f45c82018-02-16 11:23:49 +0100932 struct tls_keys_ref *ref;
Emeric Brun9e754772019-01-10 17:51:55 +0100933 union tls_sess_key *keys;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100934 struct connection *conn;
935 int head;
936 int i;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100937 int ret = -1; /* error by default */
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100938
Thierry FOURNIER28962c92018-06-17 21:37:05 +0200939 conn = SSL_get_ex_data(s, ssl_app_data_index);
Willy Tarreau07d94e42018-09-20 10:57:52 +0200940 ref = __objt_listener(conn->target)->bind_conf->keys_ref;
Christopher Faulet16f45c82018-02-16 11:23:49 +0100941 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
942
943 keys = ref->tlskeys;
944 head = ref->tls_ticket_enc_index;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100945
946 if (enc) {
947 memcpy(key_name, keys[head].name, 16);
948
949 if(!RAND_pseudo_bytes(iv, EVP_MAX_IV_LENGTH))
Christopher Faulet16f45c82018-02-16 11:23:49 +0100950 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100951
Emeric Brun9e754772019-01-10 17:51:55 +0100952 if (ref->key_size_bits == 128) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100953
Emeric Brun9e754772019-01-10 17:51:55 +0100954 if(!EVP_EncryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[head].key_128.aes_key, iv))
955 goto end;
956
Willy Tarreau9356dac2019-05-10 09:22:53 +0200957 HMAC_Init_ex(hctx, keys[head].key_128.hmac_key, 16, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100958 ret = 1;
959 }
960 else if (ref->key_size_bits == 256 ) {
961
962 if(!EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[head].key_256.aes_key, iv))
963 goto end;
964
Willy Tarreau9356dac2019-05-10 09:22:53 +0200965 HMAC_Init_ex(hctx, keys[head].key_256.hmac_key, 32, TLS_TICKET_HASH_FUNCT(), NULL);
Emeric Brun9e754772019-01-10 17:51:55 +0100966 ret = 1;
967 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100968 } else {
969 for (i = 0; i < TLS_TICKETS_NO; i++) {
970 if (!memcmp(key_name, keys[(head + i) % TLS_TICKETS_NO].name, 16))
971 goto found;
972 }
Christopher Faulet16f45c82018-02-16 11:23:49 +0100973 ret = 0;
974 goto end;
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100975
Christopher Faulet16f45c82018-02-16 11:23:49 +0100976 found:
Emeric Brun9e754772019-01-10 17:51:55 +0100977 if (ref->key_size_bits == 128) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200978 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 +0100979 if(!EVP_DecryptInit_ex(ectx, EVP_aes_128_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_128.aes_key, iv))
980 goto end;
981 /* 2 for key renewal, 1 if current key is still valid */
982 ret = i ? 2 : 1;
983 }
984 else if (ref->key_size_bits == 256) {
Willy Tarreau9356dac2019-05-10 09:22:53 +0200985 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 +0100986 if(!EVP_DecryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, keys[(head + i) % TLS_TICKETS_NO].key_256.aes_key, iv))
987 goto end;
988 /* 2 for key renewal, 1 if current key is still valid */
989 ret = i ? 2 : 1;
990 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +0100991 }
Emeric Brun9e754772019-01-10 17:51:55 +0100992
Christopher Faulet16f45c82018-02-16 11:23:49 +0100993 end:
994 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
995 return ret;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +0200996}
997
998struct tls_keys_ref *tlskeys_ref_lookup(const char *filename)
999{
1000 struct tls_keys_ref *ref;
1001
1002 list_for_each_entry(ref, &tlskeys_reference, list)
1003 if (ref->filename && strcmp(filename, ref->filename) == 0)
1004 return ref;
1005 return NULL;
1006}
1007
1008struct tls_keys_ref *tlskeys_ref_lookupid(int unique_id)
1009{
1010 struct tls_keys_ref *ref;
1011
1012 list_for_each_entry(ref, &tlskeys_reference, list)
1013 if (ref->unique_id == unique_id)
1014 return ref;
1015 return NULL;
1016}
1017
Emeric Brun9e754772019-01-10 17:51:55 +01001018/* Update the key into ref: if keysize doesnt
1019 * match existing ones, this function returns -1
1020 * else it returns 0 on success.
1021 */
1022int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
Willy Tarreau83061a82018-07-13 11:56:34 +02001023 struct buffer *tlskey)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001024{
Emeric Brun9e754772019-01-10 17:51:55 +01001025 if (ref->key_size_bits == 128) {
1026 if (tlskey->data != sizeof(struct tls_sess_key_128))
1027 return -1;
1028 }
1029 else if (ref->key_size_bits == 256) {
1030 if (tlskey->data != sizeof(struct tls_sess_key_256))
1031 return -1;
1032 }
1033 else
1034 return -1;
1035
Christopher Faulet16f45c82018-02-16 11:23:49 +01001036 HA_RWLOCK_WRLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001037 memcpy((char *) (ref->tlskeys + ((ref->tls_ticket_enc_index + 2) % TLS_TICKETS_NO)),
1038 tlskey->area, tlskey->data);
Christopher Faulet16f45c82018-02-16 11:23:49 +01001039 ref->tls_ticket_enc_index = (ref->tls_ticket_enc_index + 1) % TLS_TICKETS_NO;
1040 HA_RWLOCK_WRUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Emeric Brun9e754772019-01-10 17:51:55 +01001041
1042 return 0;
Christopher Faulet16f45c82018-02-16 11:23:49 +01001043}
1044
Willy Tarreau83061a82018-07-13 11:56:34 +02001045int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
Christopher Faulet16f45c82018-02-16 11:23:49 +01001046{
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001047 struct tls_keys_ref *ref = tlskeys_ref_lookup(filename);
1048
1049 if(!ref) {
1050 memprintf(err, "Unable to locate the referenced filename: %s", filename);
1051 return 1;
1052 }
Emeric Brun9e754772019-01-10 17:51:55 +01001053 if (ssl_sock_update_tlskey_ref(ref, tlskey) < 0) {
1054 memprintf(err, "Invalid key size");
1055 return 1;
1056 }
1057
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001058 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001059}
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001060
1061/* This function finalize the configuration parsing. Its set all the
Willy Tarreaud1c57502016-12-22 22:46:15 +01001062 * automatic ids. It's called just after the basic checks. It returns
1063 * 0 on success otherwise ERR_*.
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001064 */
Willy Tarreaud1c57502016-12-22 22:46:15 +01001065static int tlskeys_finalize_config(void)
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001066{
1067 int i = 0;
1068 struct tls_keys_ref *ref, *ref2, *ref3;
1069 struct list tkr = LIST_HEAD_INIT(tkr);
1070
1071 list_for_each_entry(ref, &tlskeys_reference, list) {
1072 if (ref->unique_id == -1) {
1073 /* Look for the first free id. */
1074 while (1) {
1075 list_for_each_entry(ref2, &tlskeys_reference, list) {
1076 if (ref2->unique_id == i) {
1077 i++;
1078 break;
1079 }
1080 }
1081 if (&ref2->list == &tlskeys_reference)
1082 break;
1083 }
1084
1085 /* Uses the unique id and increment it for the next entry. */
1086 ref->unique_id = i;
1087 i++;
1088 }
1089 }
1090
1091 /* This sort the reference list by id. */
1092 list_for_each_entry_safe(ref, ref2, &tlskeys_reference, list) {
1093 LIST_DEL(&ref->list);
1094 list_for_each_entry(ref3, &tkr, list) {
1095 if (ref->unique_id < ref3->unique_id) {
1096 LIST_ADDQ(&ref3->list, &ref->list);
1097 break;
1098 }
1099 }
1100 if (&ref3->list == &tkr)
1101 LIST_ADDQ(&tkr, &ref->list);
1102 }
1103
1104 /* swap root */
1105 LIST_ADD(&tkr, &tlskeys_reference);
1106 LIST_DEL(&tkr);
Willy Tarreaud1c57502016-12-22 22:46:15 +01001107 return 0;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02001108}
Nenad Merdanovic05552d42015-02-27 19:56:49 +01001109#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
1110
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001111#ifndef OPENSSL_NO_OCSP
yanbzhube2774d2015-12-10 15:07:30 -05001112int ssl_sock_get_ocsp_arg_kt_index(int evp_keytype)
1113{
1114 switch (evp_keytype) {
1115 case EVP_PKEY_RSA:
1116 return 2;
1117 case EVP_PKEY_DSA:
1118 return 0;
1119 case EVP_PKEY_EC:
1120 return 1;
1121 }
1122
1123 return -1;
1124}
1125
Emeric Brun4147b2e2014-06-16 18:36:30 +02001126/*
1127 * Callback used to set OCSP status extension content in server hello.
1128 */
1129int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
1130{
yanbzhube2774d2015-12-10 15:07:30 -05001131 struct certificate_ocsp *ocsp;
1132 struct ocsp_cbk_arg *ocsp_arg;
1133 char *ssl_buf;
1134 EVP_PKEY *ssl_pkey;
1135 int key_type;
1136 int index;
1137
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001138 ocsp_arg = arg;
yanbzhube2774d2015-12-10 15:07:30 -05001139
1140 ssl_pkey = SSL_get_privatekey(ssl);
1141 if (!ssl_pkey)
1142 return SSL_TLSEXT_ERR_NOACK;
1143
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001144 key_type = EVP_PKEY_base_id(ssl_pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001145
1146 if (ocsp_arg->is_single && ocsp_arg->single_kt == key_type)
1147 ocsp = ocsp_arg->s_ocsp;
1148 else {
1149 /* For multiple certs per context, we have to find the correct OCSP response based on
1150 * the certificate type
1151 */
1152 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
1153
1154 if (index < 0)
1155 return SSL_TLSEXT_ERR_NOACK;
1156
1157 ocsp = ocsp_arg->m_ocsp[index];
1158
1159 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001160
1161 if (!ocsp ||
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001162 !ocsp->response.area ||
1163 !ocsp->response.data ||
Emeric Brun4f3c87a2014-06-20 15:46:13 +02001164 (ocsp->expire < now.tv_sec))
Emeric Brun4147b2e2014-06-16 18:36:30 +02001165 return SSL_TLSEXT_ERR_NOACK;
1166
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001167 ssl_buf = OPENSSL_malloc(ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001168 if (!ssl_buf)
1169 return SSL_TLSEXT_ERR_NOACK;
1170
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001171 memcpy(ssl_buf, ocsp->response.area, ocsp->response.data);
1172 SSL_set_tlsext_status_ocsp_resp(ssl, ssl_buf, ocsp->response.data);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001173
1174 return SSL_TLSEXT_ERR_OK;
1175}
1176
William Lallemand4a660132019-10-14 14:51:41 +02001177#endif
1178
1179#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001180/*
1181 * This function enables the handling of OCSP status extension on 'ctx' if a
William Lallemand246c0242019-10-11 08:59:13 +02001182 * ocsp_response buffer was found in the cert_key_and_chain. To enable OCSP
1183 * status extension, the issuer's certificate is mandatory. It should be
1184 * present in ckch->ocsp_issuer.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001185 *
William Lallemand246c0242019-10-11 08:59:13 +02001186 * In addition, the ckch->ocsp_reponse buffer is loaded as a DER format of an
1187 * OCSP response. If file is empty or content is not a valid OCSP response,
1188 * OCSP status extension is enabled but OCSP response is ignored (a warning is
1189 * displayed).
Emeric Brun4147b2e2014-06-16 18:36:30 +02001190 *
1191 * Returns 1 if no ".ocsp" file found, 0 if OCSP status extension is
Joseph Herlant017b3da2018-11-15 09:07:59 -08001192 * successfully enabled, or -1 in other error case.
Emeric Brun4147b2e2014-06-16 18:36:30 +02001193 */
William Lallemand4a660132019-10-14 14:51:41 +02001194#ifndef OPENSSL_IS_BORINGSSL
William Lallemand246c0242019-10-11 08:59:13 +02001195static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emeric Brun4147b2e2014-06-16 18:36:30 +02001196{
William Lallemand246c0242019-10-11 08:59:13 +02001197 X509 *x = NULL, *issuer = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001198 OCSP_CERTID *cid = NULL;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001199 char ocsp_path[MAXPATHLEN+1];
1200 int i, ret = -1;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001201 struct certificate_ocsp *ocsp = NULL, *iocsp;
1202 char *warn = NULL;
1203 unsigned char *p;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001204 void (*callback) (void);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001205
Emeric Brun4147b2e2014-06-16 18:36:30 +02001206
William Lallemand246c0242019-10-11 08:59:13 +02001207 x = ckch->cert;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001208 if (!x)
1209 goto out;
1210
William Lallemand246c0242019-10-11 08:59:13 +02001211 issuer = ckch->ocsp_issuer;
1212 if (!issuer)
1213 goto out;
Emeric Brun4147b2e2014-06-16 18:36:30 +02001214
1215 cid = OCSP_cert_to_id(0, x, issuer);
1216 if (!cid)
1217 goto out;
1218
1219 i = i2d_OCSP_CERTID(cid, NULL);
1220 if (!i || (i > OCSP_MAX_CERTID_ASN1_LENGTH))
1221 goto out;
1222
Vincent Bernat02779b62016-04-03 13:48:43 +02001223 ocsp = calloc(1, sizeof(*ocsp));
Emeric Brun4147b2e2014-06-16 18:36:30 +02001224 if (!ocsp)
1225 goto out;
1226
1227 p = ocsp->key_data;
1228 i2d_OCSP_CERTID(cid, &p);
1229
1230 iocsp = (struct certificate_ocsp *)ebmb_insert(&cert_ocsp_tree, &ocsp->key, OCSP_MAX_CERTID_ASN1_LENGTH);
1231 if (iocsp == ocsp)
1232 ocsp = NULL;
1233
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001234#ifndef SSL_CTX_get_tlsext_status_cb
1235# define SSL_CTX_get_tlsext_status_cb(ctx, cb) \
1236 *cb = (void (*) (void))ctx->tlsext_status_cb;
1237#endif
1238 SSL_CTX_get_tlsext_status_cb(ctx, &callback);
1239
1240 if (!callback) {
Vincent Bernat02779b62016-04-03 13:48:43 +02001241 struct ocsp_cbk_arg *cb_arg = calloc(1, sizeof(*cb_arg));
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001242 EVP_PKEY *pkey;
yanbzhube2774d2015-12-10 15:07:30 -05001243
1244 cb_arg->is_single = 1;
1245 cb_arg->s_ocsp = iocsp;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001246
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001247 pkey = X509_get_pubkey(x);
1248 cb_arg->single_kt = EVP_PKEY_base_id(pkey);
1249 EVP_PKEY_free(pkey);
yanbzhube2774d2015-12-10 15:07:30 -05001250
1251 SSL_CTX_set_tlsext_status_cb(ctx, ssl_sock_ocsp_stapling_cbk);
1252 SSL_CTX_set_tlsext_status_arg(ctx, cb_arg);
1253 } else {
1254 /*
1255 * If the ctx has a status CB, then we have previously set an OCSP staple for this ctx
1256 * Update that cb_arg with the new cert's staple
1257 */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001258 struct ocsp_cbk_arg *cb_arg;
yanbzhube2774d2015-12-10 15:07:30 -05001259 struct certificate_ocsp *tmp_ocsp;
1260 int index;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001261 int key_type;
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001262 EVP_PKEY *pkey;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001263
1264#ifdef SSL_CTX_get_tlsext_status_arg
1265 SSL_CTX_ctrl(ctx, SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG, 0, &cb_arg);
1266#else
1267 cb_arg = ctx->tlsext_status_arg;
1268#endif
yanbzhube2774d2015-12-10 15:07:30 -05001269
1270 /*
1271 * The following few lines will convert cb_arg from a single ocsp to multi ocsp
1272 * the order of operations below matter, take care when changing it
1273 */
1274 tmp_ocsp = cb_arg->s_ocsp;
1275 index = ssl_sock_get_ocsp_arg_kt_index(cb_arg->single_kt);
1276 cb_arg->s_ocsp = NULL;
1277 cb_arg->m_ocsp[index] = tmp_ocsp;
1278 cb_arg->is_single = 0;
1279 cb_arg->single_kt = 0;
1280
Emmanuel Hocdetb7a4c342017-01-06 12:57:46 +01001281 pkey = X509_get_pubkey(x);
1282 key_type = EVP_PKEY_base_id(pkey);
1283 EVP_PKEY_free(pkey);
1284
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001285 index = ssl_sock_get_ocsp_arg_kt_index(key_type);
yanbzhube2774d2015-12-10 15:07:30 -05001286 if (index >= 0 && !cb_arg->m_ocsp[index])
1287 cb_arg->m_ocsp[index] = iocsp;
1288
1289 }
Emeric Brun4147b2e2014-06-16 18:36:30 +02001290
1291 ret = 0;
1292
1293 warn = NULL;
William Lallemand246c0242019-10-11 08:59:13 +02001294 if (ssl_sock_load_ocsp_response(ckch->ocsp_response, ocsp, cid, &warn)) {
Emeric Brun4147b2e2014-06-16 18:36:30 +02001295 memprintf(&warn, "Loading '%s': %s. Content will be ignored", ocsp_path, warn ? warn : "failure");
Christopher Faulet767a84b2017-11-24 16:50:31 +01001296 ha_warning("%s.\n", warn);
Emeric Brun4147b2e2014-06-16 18:36:30 +02001297 }
1298
1299out:
Emeric Brun4147b2e2014-06-16 18:36:30 +02001300 if (cid)
1301 OCSP_CERTID_free(cid);
1302
1303 if (ocsp)
1304 free(ocsp);
1305
1306 if (warn)
1307 free(warn);
1308
Emeric Brun4147b2e2014-06-16 18:36:30 +02001309 return ret;
1310}
William Lallemand4a660132019-10-14 14:51:41 +02001311#else /* OPENSSL_IS_BORINGSSL */
1312static int ssl_sock_load_ocsp(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001313{
William Lallemand4a660132019-10-14 14:51:41 +02001314 return SSL_CTX_set_ocsp_response(ctx, (const uint8_t *)ckch->ocsp_response->area, ckch->ocsp_response->data);
Emmanuel Hocdet2c32d8f2017-05-22 14:58:00 +02001315}
1316#endif
1317
William Lallemand4a660132019-10-14 14:51:41 +02001318#endif
1319
1320
Willy Tarreau5db847a2019-05-09 14:13:35 +02001321#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001322
1323#define CT_EXTENSION_TYPE 18
1324
1325static int sctl_ex_index = -1;
1326
1327/*
1328 * Try to parse Signed Certificate Timestamp List structure. This function
1329 * makes only basic test if the data seems like SCTL. No signature validation
1330 * is performed.
1331 */
Willy Tarreau83061a82018-07-13 11:56:34 +02001332static int ssl_sock_parse_sctl(struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001333{
1334 int ret = 1;
1335 int len, pos, sct_len;
1336 unsigned char *data;
1337
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001338 if (sctl->data < 2)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001339 goto out;
1340
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001341 data = (unsigned char *) sctl->area;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001342 len = (data[0] << 8) | data[1];
1343
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001344 if (len + 2 != sctl->data)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001345 goto out;
1346
1347 data = data + 2;
1348 pos = 0;
1349 while (pos < len) {
1350 if (len - pos < 2)
1351 goto out;
1352
1353 sct_len = (data[pos] << 8) | data[pos + 1];
1354 if (pos + sct_len + 2 > len)
1355 goto out;
1356
1357 pos += sct_len + 2;
1358 }
1359
1360 ret = 0;
1361
1362out:
1363 return ret;
1364}
1365
Willy Tarreau83061a82018-07-13 11:56:34 +02001366static int ssl_sock_load_sctl_from_file(const char *sctl_path,
1367 struct buffer **sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001368{
1369 int fd = -1;
1370 int r = 0;
1371 int ret = 1;
1372
1373 *sctl = NULL;
1374
1375 fd = open(sctl_path, O_RDONLY);
1376 if (fd == -1)
1377 goto end;
1378
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001379 trash.data = 0;
1380 while (trash.data < trash.size) {
1381 r = read(fd, trash.area + trash.data, trash.size - trash.data);
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001382 if (r < 0) {
1383 if (errno == EINTR)
1384 continue;
1385
1386 goto end;
1387 }
1388 else if (r == 0) {
1389 break;
1390 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001391 trash.data += r;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001392 }
1393
1394 ret = ssl_sock_parse_sctl(&trash);
1395 if (ret)
1396 goto end;
1397
Vincent Bernat02779b62016-04-03 13:48:43 +02001398 *sctl = calloc(1, sizeof(**sctl));
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001399 if (!chunk_dup(*sctl, &trash)) {
1400 free(*sctl);
1401 *sctl = NULL;
1402 goto end;
1403 }
1404
1405end:
1406 if (fd != -1)
1407 close(fd);
1408
1409 return ret;
1410}
1411
1412int ssl_sock_sctl_add_cbk(SSL *ssl, unsigned ext_type, const unsigned char **out, size_t *outlen, int *al, void *add_arg)
1413{
Willy Tarreau83061a82018-07-13 11:56:34 +02001414 struct buffer *sctl = add_arg;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001415
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001416 *out = (unsigned char *) sctl->area;
1417 *outlen = sctl->data;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001418
1419 return 1;
1420}
1421
1422int ssl_sock_sctl_parse_cbk(SSL *s, unsigned int ext_type, const unsigned char *in, size_t inlen, int *al, void *parse_arg)
1423{
1424 return 1;
1425}
1426
William Lallemanda17f4112019-10-10 15:16:44 +02001427static int ssl_sock_load_sctl(SSL_CTX *ctx, struct buffer *sctl)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001428{
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001429 int ret = -1;
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001430
William Lallemanda17f4112019-10-10 15:16:44 +02001431 if (!SSL_CTX_add_server_custom_ext(ctx, CT_EXTENSION_TYPE, ssl_sock_sctl_add_cbk, NULL, sctl, ssl_sock_sctl_parse_cbk, NULL))
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001432 goto out;
1433
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +01001434 SSL_CTX_set_ex_data(ctx, sctl_ex_index, sctl);
1435
1436 ret = 0;
1437
1438out:
1439 return ret;
1440}
1441
1442#endif
1443
Emeric Brune1f38db2012-09-03 20:36:47 +02001444void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
1445{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001446 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001447 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001448 BIO *write_bio;
Willy Tarreau622317d2015-02-27 16:36:16 +01001449 (void)ret; /* shut gcc stupid warning */
Emeric Brune1f38db2012-09-03 20:36:47 +02001450
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001451#ifndef SSL_OP_NO_RENEGOTIATION
1452 /* Please note that BoringSSL defines this macro to zero so don't
1453 * change this to #if and do not assign a default value to this macro!
1454 */
Emeric Brune1f38db2012-09-03 20:36:47 +02001455 if (where & SSL_CB_HANDSHAKE_START) {
1456 /* Disable renegotiation (CVE-2009-3555) */
Olivier Houchard90084a12017-11-23 18:21:29 +01001457 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 +02001458 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01001459 conn->err_code = CO_ER_SSL_RENEG;
1460 }
Emeric Brune1f38db2012-09-03 20:36:47 +02001461 }
Dirkjan Bussink526894f2019-01-21 09:35:03 -08001462#endif
Emeric Brund8b2bb52014-01-28 15:43:53 +01001463
1464 if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001465 if (!(ctx->xprt_st & SSL_SOCK_ST_FL_16K_WBFSIZE)) {
Emeric Brund8b2bb52014-01-28 15:43:53 +01001466 /* Long certificate chains optimz
1467 If write and read bios are differents, we
1468 consider that the buffering was activated,
1469 so we rise the output buffer size from 4k
1470 to 16k */
1471 write_bio = SSL_get_wbio(ssl);
1472 if (write_bio != SSL_get_rbio(ssl)) {
1473 BIO_set_write_buffer_size(write_bio, 16384);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001474 ctx->xprt_st |= SSL_SOCK_ST_FL_16K_WBFSIZE;
Emeric Brund8b2bb52014-01-28 15:43:53 +01001475 }
1476 }
1477 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02001478}
1479
Emeric Brune64aef12012-09-21 13:15:06 +02001480/* Callback is called for each certificate of the chain during a verify
1481 ok is set to 1 if preverify detect no error on current certificate.
1482 Returns 0 to break the handshake, 1 otherwise. */
Evan Broderbe554312013-06-27 00:05:25 -07001483int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
Emeric Brune64aef12012-09-21 13:15:06 +02001484{
1485 SSL *ssl;
1486 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001487 struct ssl_sock_ctx *ctx;
Emeric Brun81c00f02012-09-21 14:31:21 +02001488 int err, depth;
Emeric Brune64aef12012-09-21 13:15:06 +02001489
1490 ssl = X509_STORE_CTX_get_ex_data(x_store, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001491 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emeric Brune64aef12012-09-21 13:15:06 +02001492
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001493 ctx = conn->xprt_ctx;
1494
1495 ctx->xprt_st |= SSL_SOCK_ST_FL_VERIFY_DONE;
Emeric Brune64aef12012-09-21 13:15:06 +02001496
Emeric Brun81c00f02012-09-21 14:31:21 +02001497 if (ok) /* no errors */
1498 return ok;
1499
1500 depth = X509_STORE_CTX_get_error_depth(x_store);
1501 err = X509_STORE_CTX_get_error(x_store);
1502
1503 /* check if CA error needs to be ignored */
1504 if (depth > 0) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001505 if (!SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st)) {
1506 ctx->xprt_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
1507 ctx->xprt_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
Emeric Brunf282a812012-09-21 15:27:54 +02001508 }
1509
Willy Tarreau07d94e42018-09-20 10:57:52 +02001510 if (__objt_listener(conn->target)->bind_conf->ca_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001511 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001512 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001513 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001514 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001515
Willy Tarreau20879a02012-12-03 16:32:10 +01001516 conn->err_code = CO_ER_SSL_CA_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001517 return 0;
1518 }
1519
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001520 if (!SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st))
1521 ctx->xprt_st |= SSL_SOCK_CRTERROR_TO_ST(err);
Emeric Brunf282a812012-09-21 15:27:54 +02001522
Emeric Brun81c00f02012-09-21 14:31:21 +02001523 /* check if certificate error needs to be ignored */
Willy Tarreau07d94e42018-09-20 10:57:52 +02001524 if (__objt_listener(conn->target)->bind_conf->crt_ignerr & (1ULL << err)) {
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02001525 ssl_sock_dump_errors(conn);
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001526 ERR_clear_error();
Emeric Brun81c00f02012-09-21 14:31:21 +02001527 return 1;
Emeric Brun1eb20ef2012-12-03 13:24:29 +01001528 }
Emeric Brun81c00f02012-09-21 14:31:21 +02001529
Willy Tarreau20879a02012-12-03 16:32:10 +01001530 conn->err_code = CO_ER_SSL_CRT_FAIL;
Emeric Brun81c00f02012-09-21 14:31:21 +02001531 return 0;
Emeric Brune64aef12012-09-21 13:15:06 +02001532}
1533
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001534static inline
1535void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001536 const void *buf, size_t len, SSL *ssl)
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001537{
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001538 struct ssl_capture *capture;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001539 unsigned char *msg;
1540 unsigned char *end;
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001541 size_t rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001542
1543 /* This function is called for "from client" and "to server"
1544 * connections. The combination of write_p == 0 and content_type == 22
Joseph Herlant017b3da2018-11-15 09:07:59 -08001545 * is only available during "from client" connection.
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001546 */
1547
1548 /* "write_p" is set to 0 is the bytes are received messages,
1549 * otherwise it is set to 1.
1550 */
1551 if (write_p != 0)
1552 return;
1553
1554 /* content_type contains the type of message received or sent
1555 * according with the SSL/TLS protocol spec. This message is
1556 * encoded with one byte. The value 256 (two bytes) is used
1557 * for designing the SSL/TLS record layer. According with the
1558 * rfc6101, the expected message (other than 256) are:
1559 * - change_cipher_spec(20)
1560 * - alert(21)
1561 * - handshake(22)
1562 * - application_data(23)
1563 * - (255)
1564 * We are interessed by the handshake and specially the client
1565 * hello.
1566 */
1567 if (content_type != 22)
1568 return;
1569
1570 /* The message length is at least 4 bytes, containing the
1571 * message type and the message length.
1572 */
1573 if (len < 4)
1574 return;
1575
1576 /* First byte of the handshake message id the type of
1577 * message. The konwn types are:
1578 * - hello_request(0)
1579 * - client_hello(1)
1580 * - server_hello(2)
1581 * - certificate(11)
1582 * - server_key_exchange (12)
1583 * - certificate_request(13)
1584 * - server_hello_done(14)
1585 * We are interested by the client hello.
1586 */
1587 msg = (unsigned char *)buf;
1588 if (msg[0] != 1)
1589 return;
1590
1591 /* Next three bytes are the length of the message. The total length
1592 * must be this decoded length + 4. If the length given as argument
1593 * is not the same, we abort the protocol dissector.
1594 */
1595 rec_len = (msg[1] << 16) + (msg[2] << 8) + msg[3];
1596 if (len < rec_len + 4)
1597 return;
1598 msg += 4;
1599 end = msg + rec_len;
1600 if (end < msg)
1601 return;
1602
1603 /* Expect 2 bytes for protocol version (1 byte for major and 1 byte
1604 * for minor, the random, composed by 4 bytes for the unix time and
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001605 * 28 bytes for unix payload. So we jump 1 + 1 + 4 + 28.
1606 */
1607 msg += 1 + 1 + 4 + 28;
1608 if (msg > end)
1609 return;
1610
1611 /* Next, is session id:
1612 * if present, we have to jump by length + 1 for the size information
1613 * if not present, we have to jump by 1 only
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001614 */
Baptiste Assmann6be139f2018-11-28 15:20:25 +01001615 if (msg[0] > 0)
1616 msg += msg[0];
1617 msg += 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001618 if (msg > end)
1619 return;
1620
1621 /* Next two bytes are the ciphersuite length. */
1622 if (msg + 2 > end)
1623 return;
1624 rec_len = (msg[0] << 8) + msg[1];
1625 msg += 2;
1626 if (msg + rec_len > end || msg + rec_len < msg)
1627 return;
1628
Willy Tarreaubafbe012017-11-24 17:34:44 +01001629 capture = pool_alloc_dirty(pool_head_ssl_capture);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001630 if (!capture)
1631 return;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001632 /* Compute the xxh64 of the ciphersuite. */
1633 capture->xxh64 = XXH64(msg, rec_len, 0);
1634
1635 /* Capture the ciphersuite. */
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001636 capture->ciphersuite_len = (global_ssl.capture_cipherlist < rec_len) ?
1637 global_ssl.capture_cipherlist : rec_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001638 memcpy(capture->ciphersuite, msg, capture->ciphersuite_len);
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001639
1640 SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01001641}
1642
Emeric Brun29f037d2014-04-25 19:05:36 +02001643/* Callback is called for ssl protocol analyse */
1644void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
1645{
Emeric Brun29f037d2014-04-25 19:05:36 +02001646#ifdef TLS1_RT_HEARTBEAT
1647 /* test heartbeat received (write_p is set to 0
1648 for a received record) */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001649 if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001650 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
William Lallemand7e1770b2019-05-13 14:31:34 +02001651 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001652 const unsigned char *p = buf;
1653 unsigned int payload;
1654
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01001655 ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001656
1657 /* Check if this is a CVE-2014-0160 exploitation attempt. */
1658 if (*p != TLS1_HB_REQUEST)
1659 return;
1660
Willy Tarreauaeed6722014-04-25 23:59:58 +02001661 if (len < 1 + 2 + 16) /* 1 type + 2 size + 0 payload + 16 padding */
Willy Tarreauf51c6982014-04-25 20:02:39 +02001662 goto kill_it;
1663
1664 payload = (p[1] * 256) + p[2];
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001665 if (3 + payload + 16 <= len)
Willy Tarreauf51c6982014-04-25 20:02:39 +02001666 return; /* OK no problem */
Willy Tarreauaeed6722014-04-25 23:59:58 +02001667 kill_it:
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001668 /* We have a clear heartbleed attack (CVE-2014-0160), the
1669 * advertised payload is larger than the advertised packet
1670 * length, so we have garbage in the buffer between the
1671 * payload and the end of the buffer (p+len). We can't know
1672 * if the SSL stack is patched, and we don't know if we can
1673 * safely wipe out the area between p+3+len and payload.
1674 * So instead, we prevent the response from being sent by
1675 * setting the max_send_fragment to 0 and we report an SSL
1676 * error, which will kill this connection. It will be reported
1677 * above as SSL_ERROR_SSL while an other handshake failure with
Willy Tarreauf51c6982014-04-25 20:02:39 +02001678 * a heartbeat message will be reported as SSL_ERROR_SYSCALL.
1679 */
Willy Tarreau3b2fdb62014-04-25 23:44:22 +02001680 ssl->max_send_fragment = 0;
Willy Tarreauf51c6982014-04-25 20:02:39 +02001681 SSLerr(SSL_F_TLS1_HEARTBEAT, SSL_R_SSL_HANDSHAKE_FAILURE);
1682 return;
1683 }
Emeric Brun29f037d2014-04-25 19:05:36 +02001684#endif
Emmanuel Hocdete3804742017-03-08 11:07:10 +01001685 if (global_ssl.capture_cipherlist > 0)
1686 ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
Emeric Brun29f037d2014-04-25 19:05:36 +02001687}
1688
Bernard Spil13c53f82018-02-15 13:34:58 +01001689#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchardc7566002018-11-20 23:33:50 +01001690static int ssl_sock_srv_select_protos(SSL *s, unsigned char **out, unsigned char *outlen,
1691 const unsigned char *in, unsigned int inlen,
1692 void *arg)
1693{
1694 struct server *srv = arg;
1695
1696 if (SSL_select_next_proto(out, outlen, in, inlen, (unsigned char *)srv->ssl_ctx.npn_str,
1697 srv->ssl_ctx.npn_len) == OPENSSL_NPN_NEGOTIATED)
1698 return SSL_TLSEXT_ERR_OK;
1699 return SSL_TLSEXT_ERR_NOACK;
1700}
1701#endif
1702
1703#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001704/* This callback is used so that the server advertises the list of
1705 * negociable protocols for NPN.
1706 */
1707static int ssl_sock_advertise_npn_protos(SSL *s, const unsigned char **data,
1708 unsigned int *len, void *arg)
1709{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001710 struct ssl_bind_conf *conf = arg;
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02001711
1712 *data = (const unsigned char *)conf->npn_str;
1713 *len = conf->npn_len;
1714 return SSL_TLSEXT_ERR_OK;
1715}
1716#endif
1717
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001718#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02001719/* This callback is used so that the server advertises the list of
1720 * negociable protocols for ALPN.
1721 */
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001722static int ssl_sock_advertise_alpn_protos(SSL *s, const unsigned char **out,
1723 unsigned char *outlen,
1724 const unsigned char *server,
1725 unsigned int server_len, void *arg)
Willy Tarreauab861d32013-04-02 02:30:41 +02001726{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001727 struct ssl_bind_conf *conf = arg;
Willy Tarreauab861d32013-04-02 02:30:41 +02001728
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01001729 if (SSL_select_next_proto((unsigned char**) out, outlen, (const unsigned char *)conf->alpn_str,
1730 conf->alpn_len, server, server_len) != OPENSSL_NPN_NEGOTIATED) {
1731 return SSL_TLSEXT_ERR_NOACK;
1732 }
Willy Tarreauab861d32013-04-02 02:30:41 +02001733 return SSL_TLSEXT_ERR_OK;
1734}
1735#endif
1736
Willy Tarreauc8ad3be2015-06-17 15:48:26 +02001737#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01001738#ifndef SSL_NO_GENERATE_CERTIFICATES
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001739
Christopher Faulet30548802015-06-11 13:39:32 +02001740/* Create a X509 certificate with the specified servername and serial. This
1741 * function returns a SSL_CTX object or NULL if an error occurs. */
Christopher Faulet7969a332015-10-09 11:15:03 +02001742static SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001743ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001744{
Christopher Faulet7969a332015-10-09 11:15:03 +02001745 X509 *cacert = bind_conf->ca_sign_cert;
1746 EVP_PKEY *capkey = bind_conf->ca_sign_pkey;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001747 SSL_CTX *ssl_ctx = NULL;
1748 X509 *newcrt = NULL;
1749 EVP_PKEY *pkey = NULL;
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001750 SSL *tmp_ssl = NULL;
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001751 CONF *ctmp = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001752 X509_NAME *name;
1753 const EVP_MD *digest;
1754 X509V3_CTX ctx;
1755 unsigned int i;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001756 int key_type;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001757
Christopher Faulet48a83322017-07-28 16:56:09 +02001758 /* Get the private key of the default certificate and use it */
Willy Tarreau5db847a2019-05-09 14:13:35 +02001759#if (HA_OPENSSL_VERSION_NUMBER >= 0x10002000L)
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001760 pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
1761#else
1762 tmp_ssl = SSL_new(bind_conf->default_ctx);
1763 if (tmp_ssl)
1764 pkey = SSL_get_privatekey(tmp_ssl);
1765#endif
1766 if (!pkey)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001767 goto mkcert_error;
1768
1769 /* Create the certificate */
1770 if (!(newcrt = X509_new()))
1771 goto mkcert_error;
1772
1773 /* Set version number for the certificate (X509v3) and the serial
1774 * number */
1775 if (X509_set_version(newcrt, 2L) != 1)
1776 goto mkcert_error;
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01001777 ASN1_INTEGER_set(X509_get_serialNumber(newcrt), _HA_ATOMIC_ADD(&ssl_ctx_serial, 1));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001778
1779 /* Set duration for the certificate */
Rosen Penev68185952018-12-14 08:47:02 -08001780 if (!X509_gmtime_adj(X509_getm_notBefore(newcrt), (long)-60*60*24) ||
1781 !X509_gmtime_adj(X509_getm_notAfter(newcrt),(long)60*60*24*365))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001782 goto mkcert_error;
1783
1784 /* set public key in the certificate */
1785 if (X509_set_pubkey(newcrt, pkey) != 1)
1786 goto mkcert_error;
1787
1788 /* Set issuer name from the CA */
1789 if (!(name = X509_get_subject_name(cacert)))
1790 goto mkcert_error;
1791 if (X509_set_issuer_name(newcrt, name) != 1)
1792 goto mkcert_error;
1793
1794 /* Set the subject name using the same, but the CN */
1795 name = X509_NAME_dup(name);
1796 if (X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1797 (const unsigned char *)servername,
1798 -1, -1, 0) != 1) {
1799 X509_NAME_free(name);
1800 goto mkcert_error;
1801 }
1802 if (X509_set_subject_name(newcrt, name) != 1) {
1803 X509_NAME_free(name);
1804 goto mkcert_error;
1805 }
1806 X509_NAME_free(name);
1807
1808 /* Add x509v3 extensions as specified */
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001809 ctmp = NCONF_new(NULL);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001810 X509V3_set_ctx(&ctx, cacert, newcrt, NULL, NULL, 0);
1811 for (i = 0; i < X509V3_EXT_SIZE; i++) {
1812 X509_EXTENSION *ext;
1813
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001814 if (!(ext = X509V3_EXT_nconf(ctmp, &ctx, x509v3_ext_names[i], x509v3_ext_values[i])))
Christopher Faulet31af49d2015-06-09 17:29:50 +02001815 goto mkcert_error;
1816 if (!X509_add_ext(newcrt, ext, -1)) {
1817 X509_EXTENSION_free(ext);
1818 goto mkcert_error;
1819 }
1820 X509_EXTENSION_free(ext);
1821 }
1822
1823 /* Sign the certificate with the CA private key */
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001824
1825 key_type = EVP_PKEY_base_id(capkey);
1826
1827 if (key_type == EVP_PKEY_DSA)
1828 digest = EVP_sha1();
1829 else if (key_type == EVP_PKEY_RSA)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001830 digest = EVP_sha256();
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02001831 else if (key_type == EVP_PKEY_EC)
Christopher Faulet7969a332015-10-09 11:15:03 +02001832 digest = EVP_sha256();
1833 else {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02001834#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000000fL) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet7969a332015-10-09 11:15:03 +02001835 int nid;
1836
1837 if (EVP_PKEY_get_default_digest_nid(capkey, &nid) <= 0)
1838 goto mkcert_error;
1839 if (!(digest = EVP_get_digestbynid(nid)))
1840 goto mkcert_error;
Christopher Faulete7db2162015-10-19 13:59:24 +02001841#else
1842 goto mkcert_error;
1843#endif
Christopher Faulet7969a332015-10-09 11:15:03 +02001844 }
1845
Christopher Faulet31af49d2015-06-09 17:29:50 +02001846 if (!(X509_sign(newcrt, capkey, digest)))
1847 goto mkcert_error;
1848
1849 /* Create and set the new SSL_CTX */
1850 if (!(ssl_ctx = SSL_CTX_new(SSLv23_server_method())))
1851 goto mkcert_error;
1852 if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
1853 goto mkcert_error;
1854 if (!SSL_CTX_use_certificate(ssl_ctx, newcrt))
1855 goto mkcert_error;
1856 if (!SSL_CTX_check_private_key(ssl_ctx))
1857 goto mkcert_error;
1858
1859 if (newcrt) X509_free(newcrt);
Christopher Faulet7969a332015-10-09 11:15:03 +02001860
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001861#ifndef OPENSSL_NO_DH
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001862 SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_get_tmp_dh);
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01001863#endif
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001864#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
1865 {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01001866 const char *ecdhe = (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe : ECDHE_DEFAULT_CURVE);
Christopher Faulet85b5a1a2015-10-09 11:46:32 +02001867 EC_KEY *ecc;
1868 int nid;
1869
1870 if ((nid = OBJ_sn2nid(ecdhe)) == NID_undef)
1871 goto end;
1872 if (!(ecc = EC_KEY_new_by_curve_name(nid)))
1873 goto end;
1874 SSL_CTX_set_tmp_ecdh(ssl_ctx, ecc);
1875 EC_KEY_free(ecc);
1876 }
1877#endif
1878 end:
Christopher Faulet31af49d2015-06-09 17:29:50 +02001879 return ssl_ctx;
1880
1881 mkcert_error:
Emmanuel Hocdeta9b84022018-10-01 18:41:36 +02001882 if (ctmp) NCONF_free(ctmp);
Emmanuel Hocdet15969292017-08-11 10:56:00 +02001883 if (tmp_ssl) SSL_free(tmp_ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001884 if (ssl_ctx) SSL_CTX_free(ssl_ctx);
1885 if (newcrt) X509_free(newcrt);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001886 return NULL;
1887}
1888
Christopher Faulet7969a332015-10-09 11:15:03 +02001889SSL_CTX *
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001890ssl_sock_create_cert(struct connection *conn, const char *servername, unsigned int key)
Christopher Faulet7969a332015-10-09 11:15:03 +02001891{
Willy Tarreau07d94e42018-09-20 10:57:52 +02001892 struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf;
Olivier Houchard66ab4982019-02-26 18:37:15 +01001893 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001894
Olivier Houchard66ab4982019-02-26 18:37:15 +01001895 return ssl_sock_do_create_cert(servername, bind_conf, ctx->ssl);
Christopher Faulet7969a332015-10-09 11:15:03 +02001896}
1897
Christopher Faulet30548802015-06-11 13:39:32 +02001898/* Do a lookup for a certificate in the LRU cache used to store generated
Emeric Brun821bb9b2017-06-15 16:37:39 +02001899 * certificates and immediately assign it to the SSL session if not null. */
Christopher Faulet30548802015-06-11 13:39:32 +02001900SSL_CTX *
Emeric Brun821bb9b2017-06-15 16:37:39 +02001901ssl_sock_assign_generated_cert(unsigned int key, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet30548802015-06-11 13:39:32 +02001902{
1903 struct lru64 *lru = NULL;
1904
1905 if (ssl_ctx_lru_tree) {
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001906 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001907 lru = lru64_lookup(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001908 if (lru && lru->domain) {
1909 if (ssl)
1910 SSL_set_SSL_CTX(ssl, (SSL_CTX *)lru->data);
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001911 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001912 return (SSL_CTX *)lru->data;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001913 }
Willy Tarreau03f4ec42018-05-17 10:56:47 +02001914 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet30548802015-06-11 13:39:32 +02001915 }
1916 return NULL;
1917}
1918
Emeric Brun821bb9b2017-06-15 16:37:39 +02001919/* Same as <ssl_sock_assign_generated_cert> but without SSL session. This
1920 * function is not thread-safe, it should only be used to check if a certificate
1921 * exists in the lru cache (with no warranty it will not be removed by another
1922 * thread). It is kept for backward compatibility. */
1923SSL_CTX *
1924ssl_sock_get_generated_cert(unsigned int key, struct bind_conf *bind_conf)
1925{
1926 return ssl_sock_assign_generated_cert(key, bind_conf, NULL);
1927}
1928
Christopher Fauletd2cab922015-07-28 16:03:47 +02001929/* Set a certificate int the LRU cache used to store generated
1930 * certificate. Return 0 on success, otherwise -1 */
1931int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001932ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int key, struct bind_conf *bind_conf)
Christopher Faulet30548802015-06-11 13:39:32 +02001933{
1934 struct lru64 *lru = NULL;
1935
1936 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001937 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001938 lru = lru64_get(key, ssl_ctx_lru_tree, bind_conf->ca_sign_cert, 0);
Emeric Brun821bb9b2017-06-15 16:37:39 +02001939 if (!lru) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001940 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001941 return -1;
Emeric Brun821bb9b2017-06-15 16:37:39 +02001942 }
Christopher Faulet30548802015-06-11 13:39:32 +02001943 if (lru->domain && lru->data)
1944 lru->free((SSL_CTX *)lru->data);
Christopher Faulet7969a332015-10-09 11:15:03 +02001945 lru64_commit(lru, ssl_ctx, bind_conf->ca_sign_cert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001946 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001947 return 0;
Christopher Faulet30548802015-06-11 13:39:32 +02001948 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02001949 return -1;
Christopher Faulet30548802015-06-11 13:39:32 +02001950}
1951
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001952/* Compute the key of the certificate. */
Christopher Faulet30548802015-06-11 13:39:32 +02001953unsigned int
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001954ssl_sock_generated_cert_key(const void *data, size_t len)
Christopher Faulet30548802015-06-11 13:39:32 +02001955{
1956 return XXH32(data, len, ssl_ctx_lru_seed);
1957}
1958
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001959/* Generate a cert and immediately assign it to the SSL session so that the cert's
1960 * refcount is maintained regardless of the cert's presence in the LRU cache.
1961 */
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001962static int
Christopher Faulet7969a332015-10-09 11:15:03 +02001963ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_conf, SSL *ssl)
Christopher Faulet31af49d2015-06-09 17:29:50 +02001964{
1965 X509 *cacert = bind_conf->ca_sign_cert;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001966 SSL_CTX *ssl_ctx = NULL;
1967 struct lru64 *lru = NULL;
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001968 unsigned int key;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001969
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001970 key = ssl_sock_generated_cert_key(servername, strlen(servername));
Christopher Faulet31af49d2015-06-09 17:29:50 +02001971 if (ssl_ctx_lru_tree) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001972 HA_RWLOCK_WRLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001973 lru = lru64_get(key, ssl_ctx_lru_tree, cacert, 0);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001974 if (lru && lru->domain)
1975 ssl_ctx = (SSL_CTX *)lru->data;
Christopher Fauletd2cab922015-07-28 16:03:47 +02001976 if (!ssl_ctx && lru) {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001977 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Christopher Faulet31af49d2015-06-09 17:29:50 +02001978 lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
Christopher Fauletd2cab922015-07-28 16:03:47 +02001979 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001980 SSL_set_SSL_CTX(ssl, ssl_ctx);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001981 HA_RWLOCK_WRUNLOCK(SSL_GEN_CERTS_LOCK, &ssl_ctx_lru_rwlock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001982 return 1;
Christopher Faulet31af49d2015-06-09 17:29:50 +02001983 }
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001984 else {
Christopher Faulet635c0ad2015-11-12 11:35:51 +01001985 ssl_ctx = ssl_sock_do_create_cert(servername, bind_conf, ssl);
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001986 SSL_set_SSL_CTX(ssl, ssl_ctx);
1987 /* No LRU cache, this CTX will be released as soon as the session dies */
1988 SSL_CTX_free(ssl_ctx);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001989 return 1;
Willy Tarreau2f63ef42015-10-20 15:16:01 +02001990 }
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001991 return 0;
1992}
1993static int
1994ssl_sock_generate_certificate_from_conn(struct bind_conf *bind_conf, SSL *ssl)
1995{
1996 unsigned int key;
Thierry FOURNIER28962c92018-06-17 21:37:05 +02001997 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02001998
Willy Tarreauf5bdb642019-07-17 11:29:32 +02001999 if (conn_get_dst(conn)) {
Willy Tarreau085a1512019-07-17 14:47:35 +02002000 key = ssl_sock_generated_cert_key(conn->dst, get_addr_len(conn->dst));
Emeric Brun821bb9b2017-06-15 16:37:39 +02002001 if (ssl_sock_assign_generated_cert(key, bind_conf, ssl))
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002002 return 1;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002003 }
2004 return 0;
Christopher Faulet31af49d2015-06-09 17:29:50 +02002005}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002006#endif /* !defined SSL_NO_GENERATE_CERTIFICATES */
Christopher Faulet31af49d2015-06-09 17:29:50 +02002007
Willy Tarreau9a1ab082019-05-09 13:26:41 +02002008#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002009typedef enum { SET_CLIENT, SET_SERVER } set_context_func;
2010
2011static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002012{
Emmanuel Hocdet23877ab2017-07-12 12:53:02 +02002013#if SSL_OP_NO_SSLv3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002014 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, SSLv3_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002015 : SSL_CTX_set_ssl_version(ctx, SSLv3_client_method());
2016#endif
2017}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002018static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2019 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002020 : SSL_CTX_set_ssl_version(ctx, TLSv1_client_method());
2021}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002022static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002023#if SSL_OP_NO_TLSv1_1
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002024 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_1_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002025 : SSL_CTX_set_ssl_version(ctx, TLSv1_1_client_method());
2026#endif
2027}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002028static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002029#if SSL_OP_NO_TLSv1_2
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002030 c == SET_SERVER ? SSL_CTX_set_ssl_version(ctx, TLSv1_2_server_method())
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002031 : SSL_CTX_set_ssl_version(ctx, TLSv1_2_client_method());
2032#endif
2033}
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002034/* TLSv1.2 is the last supported version in this context. */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002035static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {}
2036/* Unusable in this context. */
2037static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {}
2038static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {}
2039static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {}
2040static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {}
2041static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {}
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002042#else /* openssl >= 1.1.0 */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002043typedef enum { SET_MIN, SET_MAX } set_context_func;
2044
2045static void ctx_set_SSLv3_func(SSL_CTX *ctx, set_context_func c) {
2046 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, SSL3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002047 : SSL_CTX_set_min_proto_version(ctx, SSL3_VERSION);
2048}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002049static void ssl_set_SSLv3_func(SSL *ssl, set_context_func c) {
2050 c == SET_MAX ? SSL_set_max_proto_version(ssl, SSL3_VERSION)
2051 : SSL_set_min_proto_version(ssl, SSL3_VERSION);
2052}
2053static void ctx_set_TLSv10_func(SSL_CTX *ctx, set_context_func c) {
2054 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002055 : SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2056}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002057static void ssl_set_TLSv10_func(SSL *ssl, set_context_func c) {
2058 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_VERSION)
2059 : SSL_set_min_proto_version(ssl, TLS1_VERSION);
2060}
2061static void ctx_set_TLSv11_func(SSL_CTX *ctx, set_context_func c) {
2062 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_1_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002063 : SSL_CTX_set_min_proto_version(ctx, TLS1_1_VERSION);
2064}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002065static void ssl_set_TLSv11_func(SSL *ssl, set_context_func c) {
2066 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_1_VERSION)
2067 : SSL_set_min_proto_version(ssl, TLS1_1_VERSION);
2068}
2069static void ctx_set_TLSv12_func(SSL_CTX *ctx, set_context_func c) {
2070 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002071 : SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
2072}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002073static void ssl_set_TLSv12_func(SSL *ssl, set_context_func c) {
2074 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_2_VERSION)
2075 : SSL_set_min_proto_version(ssl, TLS1_2_VERSION);
2076}
2077static void ctx_set_TLSv13_func(SSL_CTX *ctx, set_context_func c) {
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002078#if SSL_OP_NO_TLSv1_3
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002079 c == SET_MAX ? SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION)
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002080 : SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
2081#endif
2082}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002083static void ssl_set_TLSv13_func(SSL *ssl, set_context_func c) {
2084#if SSL_OP_NO_TLSv1_3
2085 c == SET_MAX ? SSL_set_max_proto_version(ssl, TLS1_3_VERSION)
2086 : SSL_set_min_proto_version(ssl, TLS1_3_VERSION);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002087#endif
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002088}
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002089#endif
2090static void ctx_set_None_func(SSL_CTX *ctx, set_context_func c) { }
2091static void ssl_set_None_func(SSL *ssl, set_context_func c) { }
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002092
2093static struct {
2094 int option;
2095 uint16_t flag;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002096 void (*ctx_set_version)(SSL_CTX *, set_context_func);
2097 void (*ssl_set_version)(SSL *, set_context_func);
Emmanuel Hocdetecb0e232017-05-18 11:56:58 +02002098 const char *name;
2099} methodVersions[] = {
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02002100 {0, 0, ctx_set_None_func, ssl_set_None_func, "NONE"}, /* CONF_TLSV_NONE */
2101 {SSL_OP_NO_SSLv3, MC_SSL_O_NO_SSLV3, ctx_set_SSLv3_func, ssl_set_SSLv3_func, "SSLv3"}, /* CONF_SSLV3 */
2102 {SSL_OP_NO_TLSv1, MC_SSL_O_NO_TLSV10, ctx_set_TLSv10_func, ssl_set_TLSv10_func, "TLSv1.0"}, /* CONF_TLSV10 */
2103 {SSL_OP_NO_TLSv1_1, MC_SSL_O_NO_TLSV11, ctx_set_TLSv11_func, ssl_set_TLSv11_func, "TLSv1.1"}, /* CONF_TLSV11 */
2104 {SSL_OP_NO_TLSv1_2, MC_SSL_O_NO_TLSV12, ctx_set_TLSv12_func, ssl_set_TLSv12_func, "TLSv1.2"}, /* CONF_TLSV12 */
2105 {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 +02002106};
2107
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002108static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx)
2109{
2110 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk);
2111 SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx)));
2112 SSL_set_SSL_CTX(ssl, ctx);
2113}
2114
Willy Tarreau5db847a2019-05-09 14:13:35 +02002115#if ((HA_OPENSSL_VERSION_NUMBER >= 0x10101000L) || defined(OPENSSL_IS_BORINGSSL))
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002116
2117static int ssl_sock_switchctx_err_cbk(SSL *ssl, int *al, void *priv)
2118{
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002119 struct bind_conf *s = priv;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002120 (void)al; /* shut gcc stupid warning */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002121
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002122 if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) || s->generate_certs)
2123 return SSL_TLSEXT_ERR_OK;
2124 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002125}
2126
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002127#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002128static int ssl_sock_switchctx_cbk(const struct ssl_early_callback_ctx *ctx)
2129{
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002130 SSL *ssl = ctx->ssl;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002131#else
2132static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
2133{
2134#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002135 struct connection *conn;
2136 struct bind_conf *s;
2137 const uint8_t *extension_data;
2138 size_t extension_len;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002139 int has_rsa_sig = 0, has_ecdsa_sig = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002140
2141 char *wildp = NULL;
2142 const uint8_t *servername;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002143 size_t servername_len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002144 struct ebmb_node *node, *n, *node_ecdsa = NULL, *node_rsa = NULL, *node_anonymous = NULL;
Olivier Houchardc2aae742017-09-22 18:26:28 +02002145 int allow_early = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002146 int i;
2147
Thierry FOURNIER28962c92018-06-17 21:37:05 +02002148 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Willy Tarreaua8825522018-10-15 13:20:07 +02002149 s = __objt_listener(conn->target)->bind_conf;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002150
Olivier Houchard9679ac92017-10-27 14:58:08 +02002151 if (s->ssl_conf.early_data)
Olivier Houchardc2aae742017-09-22 18:26:28 +02002152 allow_early = 1;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002153#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002154 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
2155 &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002156#else
2157 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &extension_data, &extension_len)) {
2158#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002159 /*
2160 * The server_name extension was given too much extensibility when it
2161 * was written, so parsing the normal case is a bit complex.
2162 */
2163 size_t len;
2164 if (extension_len <= 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002165 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002166 /* Extract the length of the supplied list of names. */
2167 len = (*extension_data++) << 8;
2168 len |= *extension_data++;
2169 if (len + 2 != extension_len)
2170 goto abort;
2171 /*
2172 * The list in practice only has a single element, so we only consider
2173 * the first one.
2174 */
2175 if (len == 0 || *extension_data++ != TLSEXT_NAMETYPE_host_name)
2176 goto abort;
2177 extension_len = len - 1;
2178 /* Now we can finally pull out the byte array with the actual hostname. */
2179 if (extension_len <= 2)
2180 goto abort;
2181 len = (*extension_data++) << 8;
2182 len |= *extension_data++;
2183 if (len == 0 || len + 2 > extension_len || len > TLSEXT_MAXLEN_host_name
2184 || memchr(extension_data, 0, len) != NULL)
2185 goto abort;
2186 servername = extension_data;
2187 servername_len = len;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002188 } else {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002189#if (!defined SSL_NO_GENERATE_CERTIFICATES)
2190 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02002191 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002192 }
2193#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002194 /* without SNI extension, is the default_ctx (need SSL_TLSEXT_ERR_NOACK) */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002195 if (!s->strict_sni) {
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002196 ssl_sock_switchctx_set(ssl, s->default_ctx);
Olivier Houchardc2aae742017-09-22 18:26:28 +02002197 goto allow_early;
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002198 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002199 goto abort;
2200 }
2201
2202 /* extract/check clientHello informations */
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002203#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002204 if (SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002205#else
2206 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_signature_algorithms, &extension_data, &extension_len)) {
2207#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002208 uint8_t sign;
2209 size_t len;
2210 if (extension_len < 2)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002211 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002212 len = (*extension_data++) << 8;
2213 len |= *extension_data++;
2214 if (len + 2 != extension_len)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002215 goto abort;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002216 if (len % 2 != 0)
2217 goto abort;
2218 for (; len > 0; len -= 2) {
2219 extension_data++; /* hash */
2220 sign = *extension_data++;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002221 switch (sign) {
2222 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002223 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002224 break;
2225 case TLSEXT_signature_ecdsa:
2226 has_ecdsa_sig = 1;
2227 break;
2228 default:
2229 continue;
2230 }
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002231 if (has_ecdsa_sig && has_rsa_sig)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002232 break;
2233 }
2234 } else {
Bertrand Jacquina25282b2018-08-14 00:56:13 +01002235 /* without TLSEXT_TYPE_signature_algorithms extension (< TLSv1.2) */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002236 has_rsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002237 }
2238 if (has_ecdsa_sig) { /* in very rare case: has ecdsa sign but not a ECDSA cipher */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002239 const SSL_CIPHER *cipher;
2240 size_t len;
2241 const uint8_t *cipher_suites;
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002242 has_ecdsa_sig = 0;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002243#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002244 len = ctx->cipher_suites_len;
2245 cipher_suites = ctx->cipher_suites;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002246#else
2247 len = SSL_client_hello_get0_ciphers(ssl, &cipher_suites);
2248#endif
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002249 if (len % 2 != 0)
2250 goto abort;
2251 for (; len != 0; len -= 2, cipher_suites += 2) {
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002252#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002253 uint16_t cipher_suite = (cipher_suites[0] << 8) | cipher_suites[1];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002254 cipher = SSL_get_cipher_by_value(cipher_suite);
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002255#else
2256 cipher = SSL_CIPHER_find(ssl, cipher_suites);
2257#endif
Emmanuel Hocdet019f9b12017-10-02 17:12:06 +02002258 if (cipher && SSL_CIPHER_get_auth_nid(cipher) == NID_auth_ecdsa) {
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002259 has_ecdsa_sig = 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002260 break;
2261 }
2262 }
2263 }
2264
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002265 for (i = 0; i < trash.size && i < servername_len; i++) {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002266 trash.area[i] = tolower(servername[i]);
2267 if (!wildp && (trash.area[i] == '.'))
2268 wildp = &trash.area[i];
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002269 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002270 trash.area[i] = 0;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002271
William Lallemand150bfa82019-09-19 17:12:49 +02002272 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002273 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002274 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002275
2276 /* lookup a not neg filter */
2277 for (n = node; n; n = ebmb_next_dup(n)) {
2278 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002279 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002280 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002281 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002282 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002283 break;
2284 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002285 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002286 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002287 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002288 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002289 if (!node_anonymous)
2290 node_anonymous = n;
2291 break;
2292 }
2293 }
2294 }
2295 if (wildp) {
2296 /* lookup in wildcards names */
2297 node = ebst_lookup(&s->sni_w_ctx, wildp);
2298 for (n = node; n; n = ebmb_next_dup(n)) {
2299 if (!container_of(n, struct sni_ctx, name)->neg) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002300 switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002301 case TLSEXT_signature_ecdsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002302 if (!node_ecdsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002303 node_ecdsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002304 break;
2305 case TLSEXT_signature_rsa:
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002306 if (!node_rsa)
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002307 node_rsa = n;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002308 break;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002309 default: /* TLSEXT_signature_anonymous|dsa */
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002310 if (!node_anonymous)
2311 node_anonymous = n;
2312 break;
2313 }
2314 }
2315 }
2316 }
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002317 /* select by key_signature priority order */
Emmanuel Hocdet9f9b0c62018-09-03 16:29:16 +02002318 node = (has_ecdsa_sig && node_ecdsa) ? node_ecdsa
2319 : ((has_rsa_sig && node_rsa) ? node_rsa
2320 : (node_anonymous ? node_anonymous
2321 : (node_ecdsa ? node_ecdsa /* no ecdsa signature case (< TLSv1.2) */
2322 : node_rsa /* no rsa signature case (far far away) */
2323 )));
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002324 if (node) {
2325 /* switch ctx */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02002326 struct ssl_bind_conf *conf = container_of(node, struct sni_ctx, name)->conf;
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002327 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002328 if (conf) {
2329 methodVersions[conf->ssl_methods.min].ssl_set_version(ssl, SET_MIN);
2330 methodVersions[conf->ssl_methods.max].ssl_set_version(ssl, SET_MAX);
2331 if (conf->early_data)
2332 allow_early = 1;
2333 }
William Lallemand150bfa82019-09-19 17:12:49 +02002334 HA_RWLOCK_RDUNLOCK(CKCH_LOCK, &s->sni_lock);
Olivier Houchard35a63cc2017-11-02 19:04:38 +01002335 goto allow_early;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002336 }
William Lallemand150bfa82019-09-19 17:12:49 +02002337
2338 HA_RWLOCK_RDUNLOCK(CKCH_LOCK, &s->sni_lock);
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002339#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002340 if (s->generate_certs && ssl_sock_generate_certificate(trash.area, s, ssl)) {
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002341 /* switch ctx done in ssl_sock_generate_certificate */
Olivier Houchardc2aae742017-09-22 18:26:28 +02002342 goto allow_early;
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002343 }
2344#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002345 if (!s->strict_sni) {
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002346 /* no certificate match, is the default_ctx */
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002347 ssl_sock_switchctx_set(ssl, s->default_ctx);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002348 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02002349allow_early:
2350#ifdef OPENSSL_IS_BORINGSSL
2351 if (allow_early)
2352 SSL_set_early_data_enabled(ssl, 1);
2353#else
2354 if (!allow_early)
2355 SSL_set_max_early_data(ssl, 0);
2356#endif
2357 return 1;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002358 abort:
2359 /* abort handshake (was SSL_TLSEXT_ERR_ALERT_FATAL) */
2360 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002361#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet48e87552017-08-16 11:28:44 +02002362 return ssl_select_cert_error;
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02002363#else
2364 *al = SSL_AD_UNRECOGNIZED_NAME;
2365 return 0;
2366#endif
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002367}
2368
2369#else /* OPENSSL_IS_BORINGSSL */
2370
Emeric Brunfc0421f2012-09-07 17:30:07 +02002371/* Sets the SSL ctx of <ssl> to match the advertised server name. Returns a
2372 * warning when no match is found, which implies the default (first) cert
2373 * will keep being used.
2374 */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002375static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *priv)
Emeric Brunfc0421f2012-09-07 17:30:07 +02002376{
2377 const char *servername;
2378 const char *wildp = NULL;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002379 struct ebmb_node *node, *n;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002380 struct bind_conf *s = priv;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002381 int i;
2382 (void)al; /* shut gcc stupid warning */
2383
2384 servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002385 if (!servername) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002386#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002387 if (s->generate_certs && ssl_sock_generate_certificate_from_conn(s, ssl))
2388 return SSL_TLSEXT_ERR_OK;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002389#endif
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002390 if (s->strict_sni)
2391 return SSL_TLSEXT_ERR_ALERT_FATAL;
2392 ssl_sock_switchctx_set(ssl, s->default_ctx);
2393 return SSL_TLSEXT_ERR_NOACK;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002394 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02002395
Willy Tarreau19d14ef2012-10-29 16:51:55 +01002396 for (i = 0; i < trash.size; i++) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02002397 if (!servername[i])
2398 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002399 trash.area[i] = tolower(servername[i]);
2400 if (!wildp && (trash.area[i] == '.'))
2401 wildp = &trash.area[i];
Emeric Brunfc0421f2012-09-07 17:30:07 +02002402 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002403 trash.area[i] = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002404
William Lallemand150bfa82019-09-19 17:12:49 +02002405 HA_RWLOCK_RDLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002406 /* lookup in full qualified names */
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002407 node = ebst_lookup(&s->sni_ctx, trash.area);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002408
2409 /* lookup a not neg filter */
2410 for (n = node; n; n = ebmb_next_dup(n)) {
2411 if (!container_of(n, struct sni_ctx, name)->neg) {
2412 node = n;
2413 break;
Emmanuel Hocdet65623372013-01-24 17:17:15 +01002414 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002415 }
2416 if (!node && wildp) {
2417 /* lookup in wildcards names */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002418 node = ebst_lookup(&s->sni_w_ctx, wildp);
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002419 }
2420 if (!node || container_of(node, struct sni_ctx, name)->neg) {
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002421#if (!defined SSL_NO_GENERATE_CERTIFICATES)
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02002422 if (s->generate_certs && ssl_sock_generate_certificate(servername, s, ssl)) {
2423 /* switch ctx done in ssl_sock_generate_certificate */
William Lallemand150bfa82019-09-19 17:12:49 +02002424 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Christopher Faulet31af49d2015-06-09 17:29:50 +02002425 return SSL_TLSEXT_ERR_OK;
2426 }
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01002427#endif
William Lallemand150bfa82019-09-19 17:12:49 +02002428 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01002429 if (s->strict_sni)
2430 return SSL_TLSEXT_ERR_ALERT_FATAL;
2431 ssl_sock_switchctx_set(ssl, s->default_ctx);
2432 return SSL_TLSEXT_ERR_OK;
Emeric Brunfc0421f2012-09-07 17:30:07 +02002433 }
2434
2435 /* switch ctx */
Emmanuel Hocdet530141f2017-03-01 18:54:56 +01002436 ssl_sock_switchctx_set(ssl, container_of(node, struct sni_ctx, name)->ctx);
William Lallemand150bfa82019-09-19 17:12:49 +02002437 HA_RWLOCK_RDUNLOCK(SNI_LOCK, &s->sni_lock);
Emeric Brunfc0421f2012-09-07 17:30:07 +02002438 return SSL_TLSEXT_ERR_OK;
2439}
Emmanuel Hocdet05942112017-02-20 16:11:50 +01002440#endif /* (!) OPENSSL_IS_BORINGSSL */
Emeric Brunfc0421f2012-09-07 17:30:07 +02002441#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2442
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002443#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002444
2445static DH * ssl_get_dh_1024(void)
2446{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002447 static unsigned char dh1024_p[]={
2448 0xFA,0xF9,0x2A,0x22,0x2A,0xA7,0x7F,0xE1,0x67,0x4E,0x53,0xF7,
2449 0x56,0x13,0xC3,0xB1,0xE3,0x29,0x6B,0x66,0x31,0x6A,0x7F,0xB3,
2450 0xC2,0x68,0x6B,0xCB,0x1D,0x57,0x39,0x1D,0x1F,0xFF,0x1C,0xC9,
2451 0xA6,0xA4,0x98,0x82,0x31,0x5D,0x25,0xFF,0x8A,0xE0,0x73,0x96,
2452 0x81,0xC8,0x83,0x79,0xC1,0x5A,0x04,0xF8,0x37,0x0D,0xA8,0x3D,
2453 0xAE,0x74,0xBC,0xDB,0xB6,0xA4,0x75,0xD9,0x71,0x8A,0xA0,0x17,
2454 0x9E,0x2D,0xC8,0xA8,0xDF,0x2C,0x5F,0x82,0x95,0xF8,0x92,0x9B,
2455 0xA7,0x33,0x5F,0x89,0x71,0xC8,0x2D,0x6B,0x18,0x86,0xC4,0x94,
2456 0x22,0xA5,0x52,0x8D,0xF6,0xF6,0xD2,0x37,0x92,0x0F,0xA5,0xCC,
2457 0xDB,0x7B,0x1D,0x3D,0xA1,0x31,0xB7,0x80,0x8F,0x0B,0x67,0x5E,
2458 0x36,0xA5,0x60,0x0C,0xF1,0x95,0x33,0x8B,
2459 };
2460 static unsigned char dh1024_g[]={
2461 0x02,
2462 };
2463
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002464 BIGNUM *p;
2465 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002466 DH *dh = DH_new();
2467 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002468 p = BN_bin2bn(dh1024_p, sizeof dh1024_p, NULL);
2469 g = BN_bin2bn(dh1024_g, sizeof dh1024_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002470
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002471 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002472 DH_free(dh);
2473 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002474 } else {
2475 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002476 }
2477 }
2478 return dh;
2479}
2480
2481static DH *ssl_get_dh_2048(void)
2482{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002483 static unsigned char dh2048_p[]={
2484 0xEC,0x86,0xF8,0x70,0xA0,0x33,0x16,0xEC,0x05,0x1A,0x73,0x59,
2485 0xCD,0x1F,0x8B,0xF8,0x29,0xE4,0xD2,0xCF,0x52,0xDD,0xC2,0x24,
2486 0x8D,0xB5,0x38,0x9A,0xFB,0x5C,0xA4,0xE4,0xB2,0xDA,0xCE,0x66,
2487 0x50,0x74,0xA6,0x85,0x4D,0x4B,0x1D,0x30,0xB8,0x2B,0xF3,0x10,
2488 0xE9,0xA7,0x2D,0x05,0x71,0xE7,0x81,0xDF,0x8B,0x59,0x52,0x3B,
2489 0x5F,0x43,0x0B,0x68,0xF1,0xDB,0x07,0xBE,0x08,0x6B,0x1B,0x23,
2490 0xEE,0x4D,0xCC,0x9E,0x0E,0x43,0xA0,0x1E,0xDF,0x43,0x8C,0xEC,
2491 0xBE,0xBE,0x90,0xB4,0x51,0x54,0xB9,0x2F,0x7B,0x64,0x76,0x4E,
2492 0x5D,0xD4,0x2E,0xAE,0xC2,0x9E,0xAE,0x51,0x43,0x59,0xC7,0x77,
2493 0x9C,0x50,0x3C,0x0E,0xED,0x73,0x04,0x5F,0xF1,0x4C,0x76,0x2A,
2494 0xD8,0xF8,0xCF,0xFC,0x34,0x40,0xD1,0xB4,0x42,0x61,0x84,0x66,
2495 0x42,0x39,0x04,0xF8,0x68,0xB2,0x62,0xD7,0x55,0xED,0x1B,0x74,
2496 0x75,0x91,0xE0,0xC5,0x69,0xC1,0x31,0x5C,0xDB,0x7B,0x44,0x2E,
2497 0xCE,0x84,0x58,0x0D,0x1E,0x66,0x0C,0xC8,0x44,0x9E,0xFD,0x40,
2498 0x08,0x67,0x5D,0xFB,0xA7,0x76,0x8F,0x00,0x11,0x87,0xE9,0x93,
2499 0xF9,0x7D,0xC4,0xBC,0x74,0x55,0x20,0xD4,0x4A,0x41,0x2F,0x43,
2500 0x42,0x1A,0xC1,0xF2,0x97,0x17,0x49,0x27,0x37,0x6B,0x2F,0x88,
2501 0x7E,0x1C,0xA0,0xA1,0x89,0x92,0x27,0xD9,0x56,0x5A,0x71,0xC1,
2502 0x56,0x37,0x7E,0x3A,0x9D,0x05,0xE7,0xEE,0x5D,0x8F,0x82,0x17,
2503 0xBC,0xE9,0xC2,0x93,0x30,0x82,0xF9,0xF4,0xC9,0xAE,0x49,0xDB,
2504 0xD0,0x54,0xB4,0xD9,0x75,0x4D,0xFA,0x06,0xB8,0xD6,0x38,0x41,
2505 0xB7,0x1F,0x77,0xF3,
2506 };
2507 static unsigned char dh2048_g[]={
2508 0x02,
2509 };
2510
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002511 BIGNUM *p;
2512 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002513 DH *dh = DH_new();
2514 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002515 p = BN_bin2bn(dh2048_p, sizeof dh2048_p, NULL);
2516 g = BN_bin2bn(dh2048_g, sizeof dh2048_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002517
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002518 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002519 DH_free(dh);
2520 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002521 } else {
2522 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002523 }
2524 }
2525 return dh;
2526}
2527
2528static DH *ssl_get_dh_4096(void)
2529{
Remi Gacogned3a341a2015-05-29 16:26:17 +02002530 static unsigned char dh4096_p[]={
2531 0xDE,0x16,0x94,0xCD,0x99,0x58,0x07,0xF1,0xF7,0x32,0x96,0x11,
2532 0x04,0x82,0xD4,0x84,0x72,0x80,0x99,0x06,0xCA,0xF0,0xA3,0x68,
2533 0x07,0xCE,0x64,0x50,0xE7,0x74,0x45,0x20,0x80,0x5E,0x4D,0xAD,
2534 0xA5,0xB6,0xED,0xFA,0x80,0x6C,0x3B,0x35,0xC4,0x9A,0x14,0x6B,
2535 0x32,0xBB,0xFD,0x1F,0x17,0x8E,0xB7,0x1F,0xD6,0xFA,0x3F,0x7B,
2536 0xEE,0x16,0xA5,0x62,0x33,0x0D,0xED,0xBC,0x4E,0x58,0xE5,0x47,
2537 0x4D,0xE9,0xAB,0x8E,0x38,0xD3,0x6E,0x90,0x57,0xE3,0x22,0x15,
2538 0x33,0xBD,0xF6,0x43,0x45,0xB5,0x10,0x0A,0xBE,0x2C,0xB4,0x35,
2539 0xB8,0x53,0x8D,0xAD,0xFB,0xA7,0x1F,0x85,0x58,0x41,0x7A,0x79,
2540 0x20,0x68,0xB3,0xE1,0x3D,0x08,0x76,0xBF,0x86,0x0D,0x49,0xE3,
2541 0x82,0x71,0x8C,0xB4,0x8D,0x81,0x84,0xD4,0xE7,0xBE,0x91,0xDC,
2542 0x26,0x39,0x48,0x0F,0x35,0xC4,0xCA,0x65,0xE3,0x40,0x93,0x52,
2543 0x76,0x58,0x7D,0xDD,0x51,0x75,0xDC,0x69,0x61,0xBF,0x47,0x2C,
2544 0x16,0x68,0x2D,0xC9,0x29,0xD3,0xE6,0xC0,0x99,0x48,0xA0,0x9A,
2545 0xC8,0x78,0xC0,0x6D,0x81,0x67,0x12,0x61,0x3F,0x71,0xBA,0x41,
2546 0x1F,0x6C,0x89,0x44,0x03,0xBA,0x3B,0x39,0x60,0xAA,0x28,0x55,
2547 0x59,0xAE,0xB8,0xFA,0xCB,0x6F,0xA5,0x1A,0xF7,0x2B,0xDD,0x52,
2548 0x8A,0x8B,0xE2,0x71,0xA6,0x5E,0x7E,0xD8,0x2E,0x18,0xE0,0x66,
2549 0xDF,0xDD,0x22,0x21,0x99,0x52,0x73,0xA6,0x33,0x20,0x65,0x0E,
2550 0x53,0xE7,0x6B,0x9B,0xC5,0xA3,0x2F,0x97,0x65,0x76,0xD3,0x47,
2551 0x23,0x77,0x12,0xB6,0x11,0x7B,0x24,0xED,0xF1,0xEF,0xC0,0xE2,
2552 0xA3,0x7E,0x67,0x05,0x3E,0x96,0x4D,0x45,0xC2,0x18,0xD1,0x73,
2553 0x9E,0x07,0xF3,0x81,0x6E,0x52,0x63,0xF6,0x20,0x76,0xB9,0x13,
2554 0xD2,0x65,0x30,0x18,0x16,0x09,0x16,0x9E,0x8F,0xF1,0xD2,0x10,
2555 0x5A,0xD3,0xD4,0xAF,0x16,0x61,0xDA,0x55,0x2E,0x18,0x5E,0x14,
2556 0x08,0x54,0x2E,0x2A,0x25,0xA2,0x1A,0x9B,0x8B,0x32,0xA9,0xFD,
2557 0xC2,0x48,0x96,0xE1,0x80,0xCA,0xE9,0x22,0x17,0xBB,0xCE,0x3E,
2558 0x9E,0xED,0xC7,0xF1,0x1F,0xEC,0x17,0x21,0xDC,0x7B,0x82,0x48,
2559 0x8E,0xBB,0x4B,0x9D,0x5B,0x04,0x04,0xDA,0xDB,0x39,0xDF,0x01,
2560 0x40,0xC3,0xAA,0x26,0x23,0x89,0x75,0xC6,0x0B,0xD0,0xA2,0x60,
2561 0x6A,0xF1,0xCC,0x65,0x18,0x98,0x1B,0x52,0xD2,0x74,0x61,0xCC,
2562 0xBD,0x60,0xAE,0xA3,0xA0,0x66,0x6A,0x16,0x34,0x92,0x3F,0x41,
2563 0x40,0x31,0x29,0xC0,0x2C,0x63,0xB2,0x07,0x8D,0xEB,0x94,0xB8,
2564 0xE8,0x47,0x92,0x52,0x93,0x6A,0x1B,0x7E,0x1A,0x61,0xB3,0x1B,
2565 0xF0,0xD6,0x72,0x9B,0xF1,0xB0,0xAF,0xBF,0x3E,0x65,0xEF,0x23,
2566 0x1D,0x6F,0xFF,0x70,0xCD,0x8A,0x4C,0x8A,0xA0,0x72,0x9D,0xBE,
2567 0xD4,0xBB,0x24,0x47,0x4A,0x68,0xB5,0xF5,0xC6,0xD5,0x7A,0xCD,
2568 0xCA,0x06,0x41,0x07,0xAD,0xC2,0x1E,0xE6,0x54,0xA7,0xAD,0x03,
2569 0xD9,0x12,0xC1,0x9C,0x13,0xB1,0xC9,0x0A,0x43,0x8E,0x1E,0x08,
2570 0xCE,0x50,0x82,0x73,0x5F,0xA7,0x55,0x1D,0xD9,0x59,0xAC,0xB5,
2571 0xEA,0x02,0x7F,0x6C,0x5B,0x74,0x96,0x98,0x67,0x24,0xA3,0x0F,
2572 0x15,0xFC,0xA9,0x7D,0x3E,0x67,0xD1,0x70,0xF8,0x97,0xF3,0x67,
2573 0xC5,0x8C,0x88,0x44,0x08,0x02,0xC7,0x2B,
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002574 };
Remi Gacogned3a341a2015-05-29 16:26:17 +02002575 static unsigned char dh4096_g[]={
2576 0x02,
2577 };
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002578
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002579 BIGNUM *p;
2580 BIGNUM *g;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002581 DH *dh = DH_new();
2582 if (dh) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002583 p = BN_bin2bn(dh4096_p, sizeof dh4096_p, NULL);
2584 g = BN_bin2bn(dh4096_g, sizeof dh4096_g, NULL);
Remi Gacogned3a341a2015-05-29 16:26:17 +02002585
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002586 if (!p || !g) {
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002587 DH_free(dh);
2588 dh = NULL;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002589 } else {
2590 DH_set0_pqg(dh, p, NULL, g);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002591 }
2592 }
2593 return dh;
2594}
2595
2596/* Returns Diffie-Hellman parameters matching the private key length
Willy Tarreauef934602016-12-22 23:12:01 +01002597 but not exceeding global_ssl.default_dh_param */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002598static DH *ssl_get_tmp_dh(SSL *ssl, int export, int keylen)
2599{
2600 DH *dh = NULL;
2601 EVP_PKEY *pkey = SSL_get_privatekey(ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02002602 int type;
2603
2604 type = pkey ? EVP_PKEY_base_id(pkey) : EVP_PKEY_NONE;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002605
2606 /* The keylen supplied by OpenSSL can only be 512 or 1024.
2607 See ssl3_send_server_key_exchange() in ssl/s3_srvr.c
2608 */
2609 if (type == EVP_PKEY_RSA || type == EVP_PKEY_DSA) {
2610 keylen = EVP_PKEY_bits(pkey);
2611 }
2612
Willy Tarreauef934602016-12-22 23:12:01 +01002613 if (keylen > global_ssl.default_dh_param) {
2614 keylen = global_ssl.default_dh_param;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002615 }
2616
Remi Gacogned3a341a2015-05-29 16:26:17 +02002617 if (keylen >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002618 dh = local_dh_4096;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002619 }
2620 else if (keylen >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02002621 dh = local_dh_2048;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002622 }
2623 else {
Remi Gacogne8de54152014-07-15 11:36:40 +02002624 dh = local_dh_1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02002625 }
2626
2627 return dh;
2628}
2629
Remi Gacogne47783ef2015-05-29 15:53:22 +02002630static DH * ssl_sock_get_dh_from_file(const char *filename)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002631{
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002632 DH *dh = NULL;
Remi Gacogne47783ef2015-05-29 15:53:22 +02002633 BIO *in = BIO_new(BIO_s_file());
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002634
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002635 if (in == NULL)
2636 goto end;
2637
Remi Gacogne47783ef2015-05-29 15:53:22 +02002638 if (BIO_read_filename(in, filename) <= 0)
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002639 goto end;
2640
Remi Gacogne47783ef2015-05-29 15:53:22 +02002641 dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2642
2643end:
2644 if (in)
2645 BIO_free(in);
2646
Emeric Brune1b4ed42018-08-16 15:14:12 +02002647 ERR_clear_error();
2648
Remi Gacogne47783ef2015-05-29 15:53:22 +02002649 return dh;
2650}
2651
2652int ssl_sock_load_global_dh_param_from_file(const char *filename)
2653{
2654 global_dh = ssl_sock_get_dh_from_file(filename);
2655
2656 if (global_dh) {
2657 return 0;
2658 }
2659
2660 return -1;
2661}
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02002662#endif
2663
William Lallemand9117de92019-10-04 00:29:42 +02002664/* Alloc and init a ckch_inst */
2665static struct ckch_inst *ckch_inst_new()
2666{
2667 struct ckch_inst *ckch_inst;
2668
2669 ckch_inst = calloc(1, sizeof *ckch_inst);
2670 if (ckch_inst)
2671 LIST_INIT(&ckch_inst->sni_ctx);
2672
2673 return ckch_inst;
2674}
2675
2676
2677/* This function allocates a sni_ctx and adds it to the ckch_inst */
William Lallemand1d29c742019-10-04 00:53:29 +02002678static int ckch_inst_add_cert_sni(SSL_CTX *ctx, struct ckch_inst *ckch_inst,
William Lallemand9117de92019-10-04 00:29:42 +02002679 struct bind_conf *s, struct ssl_bind_conf *conf,
2680 struct pkey_info kinfo, char *name, int order)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002681{
2682 struct sni_ctx *sc;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002683 int wild = 0, neg = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002684
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002685 if (*name == '!') {
2686 neg = 1;
2687 name++;
2688 }
2689 if (*name == '*') {
2690 wild = 1;
2691 name++;
2692 }
2693 /* !* filter is a nop */
2694 if (neg && wild)
2695 return order;
2696 if (*name) {
2697 int j, len;
2698 len = strlen(name);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002699 for (j = 0; j < len && j < trash.size; j++)
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002700 trash.area[j] = tolower(name[j]);
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002701 if (j >= trash.size)
William Lallemandfe49bb32019-10-03 23:46:33 +02002702 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002703 trash.area[j] = 0;
Thierry FOURNIER / OZON.IO07c3d782016-10-06 10:56:48 +02002704
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002705 sc = malloc(sizeof(struct sni_ctx) + len + 1);
Thierry FOURNIER / OZON.IO7a3bd3b2016-10-06 10:35:29 +02002706 if (!sc)
William Lallemandfe49bb32019-10-03 23:46:33 +02002707 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02002708 memcpy(sc->name.key, trash.area, len + 1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002709 sc->ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01002710 sc->conf = conf;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02002711 sc->kinfo = kinfo;
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02002712 sc->order = order++;
2713 sc->neg = neg;
William Lallemand1d29c742019-10-04 00:53:29 +02002714 sc->wild = wild;
2715 sc->name.node.leaf_p = NULL;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01002716 if (kinfo.sig != TLSEXT_signature_anonymous)
2717 SSL_CTX_set_ex_data(ctx, ssl_pkey_info_index, &sc->kinfo);
William Lallemand9117de92019-10-04 00:29:42 +02002718
William Lallemand1d29c742019-10-04 00:53:29 +02002719 LIST_ADDQ(&ckch_inst->sni_ctx, &sc->by_ckch_inst);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01002720 }
2721 return order;
2722}
2723
William Lallemand6af03992019-07-23 15:00:54 +02002724/*
William Lallemand1d29c742019-10-04 00:53:29 +02002725 * Insert the sni_ctxs that are listed in the ckch_inst, in the bind_conf's sni_ctx tree
2726 * This function can't return an error.
2727 *
2728 * *CAUTION*: The caller must lock the sni tree if called in multithreading mode
2729 */
2730static void ssl_sock_load_cert_sni(struct ckch_inst *ckch_inst, struct bind_conf *bind_conf)
2731{
2732
2733 struct sni_ctx *sc0, *sc0b, *sc1;
2734 struct ebmb_node *node;
2735
2736 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
2737
2738 /* ignore if sc0 was already inserted in a tree */
2739 if (sc0->name.node.leaf_p)
2740 continue;
2741
2742 /* Check for duplicates. */
2743 if (sc0->wild)
2744 node = ebst_lookup(&bind_conf->sni_w_ctx, (char *)sc0->name.key);
2745 else
2746 node = ebst_lookup(&bind_conf->sni_ctx, (char *)sc0->name.key);
2747
2748 for (; node; node = ebmb_next_dup(node)) {
2749 sc1 = ebmb_entry(node, struct sni_ctx, name);
2750 if (sc1->ctx == sc0->ctx && sc1->conf == sc0->conf
2751 && sc1->neg == sc0->neg && sc1->wild == sc0->wild) {
2752 /* it's a duplicate, we should remove and free it */
2753 LIST_DEL(&sc0->by_ckch_inst);
2754 free(sc0);
2755 sc0 = NULL;
William Lallemande15029b2019-10-14 10:46:58 +02002756 break;
William Lallemand1d29c742019-10-04 00:53:29 +02002757 }
2758 }
2759
2760 /* if duplicate, ignore the insertion */
2761 if (!sc0)
2762 continue;
2763
2764 if (sc0->wild)
2765 ebst_insert(&bind_conf->sni_w_ctx, &sc0->name);
2766 else
2767 ebst_insert(&bind_conf->sni_ctx, &sc0->name);
2768 }
2769}
2770
2771/*
William Lallemande3af8fb2019-10-08 11:36:53 +02002772 * tree used to store the ckchs ordered by filename/bundle name
William Lallemand6af03992019-07-23 15:00:54 +02002773 */
William Lallemande3af8fb2019-10-08 11:36:53 +02002774struct eb_root ckchs_tree = EB_ROOT_UNIQUE;
William Lallemand6af03992019-07-23 15:00:54 +02002775
William Lallemandfa892222019-07-23 16:06:08 +02002776
William Lallemande3af8fb2019-10-08 11:36:53 +02002777/* Loads Diffie-Hellman parameter from a ckchs. Returns 1 if loaded, else -1
William Lallemandfa892222019-07-23 16:06:08 +02002778 if an error occurred, and 0 if parameter not found. */
2779#ifndef OPENSSL_NO_DH
2780static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
2781{
2782 int ret = -1;
2783 DH *dh = NULL;
2784
William Lallemanda8c73742019-07-31 18:31:34 +02002785 if (ckch && ckch->dh) {
William Lallemandfa892222019-07-23 16:06:08 +02002786 dh = ckch->dh;
William Lallemandfa892222019-07-23 16:06:08 +02002787 ret = 1;
2788 SSL_CTX_set_tmp_dh(ctx, dh);
2789
2790 if (ssl_dh_ptr_index >= 0) {
2791 /* store a pointer to the DH params to avoid complaining about
2792 ssl-default-dh-param not being set for this SSL_CTX */
2793 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
2794 }
2795 }
2796 else if (global_dh) {
2797 SSL_CTX_set_tmp_dh(ctx, global_dh);
2798 ret = 0; /* DH params not found */
2799 }
2800 else {
2801 /* Clear openssl global errors stack */
2802 ERR_clear_error();
2803
2804 if (global_ssl.default_dh_param <= 1024) {
2805 /* we are limited to DH parameter of 1024 bits anyway */
2806 if (local_dh_1024 == NULL)
2807 local_dh_1024 = ssl_get_dh_1024();
2808
2809 if (local_dh_1024 == NULL)
2810 goto end;
2811
2812 SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
2813 }
2814 else {
2815 SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
2816 }
2817
2818 ret = 0; /* DH params not found */
2819 }
2820
2821end:
William Lallemandfa892222019-07-23 16:06:08 +02002822 return ret;
2823}
2824#endif
yanbzhu08ce6ab2015-12-02 13:01:29 -05002825
yanbzhu488a4d22015-12-01 15:16:07 -05002826/* Frees the contents of a cert_key_and_chain
2827 */
2828static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
2829{
yanbzhu488a4d22015-12-01 15:16:07 -05002830 if (!ckch)
2831 return;
2832
2833 /* Free the certificate and set pointer to NULL */
2834 if (ckch->cert)
2835 X509_free(ckch->cert);
2836 ckch->cert = NULL;
2837
2838 /* Free the key and set pointer to NULL */
2839 if (ckch->key)
2840 EVP_PKEY_free(ckch->key);
2841 ckch->key = NULL;
2842
2843 /* Free each certificate in the chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002844 if (ckch->chain)
2845 sk_X509_pop_free(ckch->chain, X509_free);
2846 ckch->chain = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002847
2848}
2849
2850/* checks if a key and cert exists in the ckch
2851 */
William Lallemand1633e392019-09-30 12:58:13 +02002852#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu488a4d22015-12-01 15:16:07 -05002853static int ssl_sock_is_ckch_valid(struct cert_key_and_chain *ckch)
2854{
2855 return (ckch->cert != NULL && ckch->key != NULL);
2856}
William Lallemand1633e392019-09-30 12:58:13 +02002857#endif
yanbzhu488a4d22015-12-01 15:16:07 -05002858
William Lallemandf11365b2019-09-19 14:25:58 +02002859/* Loads the contents of a crt file (path) or BIO into a cert_key_and_chain
2860 * This allows us to carry the contents of the file without having to read the
2861 * file multiple times. The caller must call
2862 * ssl_sock_free_cert_key_and_chain_contents.
yanbzhu488a4d22015-12-01 15:16:07 -05002863 *
2864 * returns:
2865 * 0 on Success
2866 * 1 on SSL Failure
yanbzhu488a4d22015-12-01 15:16:07 -05002867 */
William Lallemandf11365b2019-09-19 14:25:58 +02002868static int ssl_sock_load_crt_file_into_ckch(const char *path, BIO *buf, struct cert_key_and_chain *ckch, char **err)
yanbzhu488a4d22015-12-01 15:16:07 -05002869{
2870
William Lallemandf11365b2019-09-19 14:25:58 +02002871 BIO *in = NULL;
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002872 X509 *ca;
yanbzhu488a4d22015-12-01 15:16:07 -05002873 int ret = 1;
2874
William Lallemandf11365b2019-09-19 14:25:58 +02002875 if (buf != NULL && path != NULL) {
2876 in = buf;
2877 } else if (path != NULL) {
2878 in = BIO_new(BIO_s_file());
2879 if (in == NULL)
2880 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05002881
William Lallemandf11365b2019-09-19 14:25:58 +02002882 if (BIO_read_filename(in, path) <= 0)
2883 goto end;
2884 } else {
yanbzhu488a4d22015-12-01 15:16:07 -05002885 goto end;
William Lallemandf11365b2019-09-19 14:25:58 +02002886 }
yanbzhu488a4d22015-12-01 15:16:07 -05002887
yanbzhu488a4d22015-12-01 15:16:07 -05002888 /* Read Private Key */
2889 ckch->key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
2890 if (ckch->key == NULL) {
2891 memprintf(err, "%sunable to load private key from file '%s'.\n",
2892 err && *err ? *err : "", path);
2893 goto end;
2894 }
2895
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02002896#ifndef OPENSSL_NO_DH
William Lallemandfa892222019-07-23 16:06:08 +02002897 /* Seek back to beginning of file */
2898 if (BIO_reset(in) == -1) {
2899 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2900 err && *err ? *err : "", path);
2901 goto end;
2902 }
2903
2904 ckch->dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
2905 /* no need to check for NULL there, dh is not mandatory */
Emmanuel Hocdet54227d82019-07-30 17:04:01 +02002906#endif
William Lallemandfa892222019-07-23 16:06:08 +02002907
Willy Tarreaubb137a82016-04-06 19:02:38 +02002908 /* Seek back to beginning of file */
Thierry FOURNIER / OZON.IOd44ea3f2016-10-14 00:49:21 +02002909 if (BIO_reset(in) == -1) {
2910 memprintf(err, "%san error occurred while reading the file '%s'.\n",
2911 err && *err ? *err : "", path);
2912 goto end;
2913 }
Willy Tarreaubb137a82016-04-06 19:02:38 +02002914
2915 /* Read Certificate */
2916 ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
2917 if (ckch->cert == NULL) {
2918 memprintf(err, "%sunable to load certificate from file '%s'.\n",
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002919 err && *err ? *err : "", path);
Willy Tarreaubb137a82016-04-06 19:02:38 +02002920 goto end;
2921 }
2922
Emmanuel Hocdet03e09f32019-07-30 14:21:25 +02002923 if (!X509_check_private_key(ckch->cert, ckch->key)) {
2924 memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
2925 err && *err ? *err : "", path);
2926 goto end;
2927 }
2928
yanbzhu488a4d22015-12-01 15:16:07 -05002929 /* Read Certificate Chain */
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01002930 ckch->chain = sk_X509_new_null();
2931 while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)))
2932 if (!sk_X509_push(ckch->chain, ca)) {
2933 X509_free(ca);
2934 goto end;
2935 }
yanbzhu488a4d22015-12-01 15:16:07 -05002936
yanbzhu488a4d22015-12-01 15:16:07 -05002937 ret = ERR_get_error();
2938 if (ret && (ERR_GET_LIB(ret) != ERR_LIB_PEM && ERR_GET_REASON(ret) != PEM_R_NO_START_LINE)) {
2939 memprintf(err, "%sunable to load certificate chain from file '%s'.\n",
2940 err && *err ? *err : "", path);
2941 ret = 1;
2942 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02002943 }
2944
2945 ret = 0;
2946
2947 /* don't try to do the next operations if we feed the ckch from the cli */
2948 if (buf)
2949 goto end;
2950
2951 ERR_clear_error();
2952 if (in) {
2953 BIO_free(in);
2954 in = NULL;
yanbzhu488a4d22015-12-01 15:16:07 -05002955 }
William Lallemanda17f4112019-10-10 15:16:44 +02002956
2957#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
2958 /* try to load the sctl file */
2959 {
2960 char fp[MAXPATHLEN+1];
2961 struct stat st;
2962
2963 snprintf(fp, MAXPATHLEN+1, "%s.sctl", path);
2964 if (stat(fp, &st) == 0) {
2965 if (ssl_sock_load_sctl_from_file(fp, &ckch->sctl)) {
2966 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
2967 *err ? *err : "", fp);
2968 ret = 1;
2969 goto end;
2970 }
2971 }
2972 }
2973#endif
yanbzhu488a4d22015-12-01 15:16:07 -05002974
William Lallemand246c0242019-10-11 08:59:13 +02002975 /* try to load an ocsp response file */
2976 {
2977 char fp[MAXPATHLEN+1];
2978 struct stat st;
2979
2980 snprintf(fp, MAXPATHLEN+1, "%s.ocsp", path);
2981 if (stat(fp, &st) == 0) {
2982 if (ssl_sock_load_ocsp_response_from_file(fp, &ckch->ocsp_response, err)) {
2983 ret = 1;
2984 goto end;
2985 }
2986 }
2987 }
2988
2989 if (ckch->ocsp_response) {
2990 X509 *issuer;
2991 int i;
2992
2993 /* check if one of the certificate of the chain is the issuer */
2994 for (i = 0; i < sk_X509_num(ckch->chain); i++) {
2995 issuer = sk_X509_value(ckch->chain, i);
2996 if (X509_check_issued(issuer, ckch->cert) == X509_V_OK) {
2997 ckch->ocsp_issuer = issuer;
2998 break;
2999 } else
3000 issuer = NULL;
3001 }
3002
3003 /* if no issuer was found, try to load an issuer from the .issuer */
3004 if (!issuer) {
3005 struct stat st;
3006 char fp[MAXPATHLEN+1];
3007
3008 snprintf(fp, MAXPATHLEN+1, "%s.issuer", path);
3009 if (stat(fp, &st) == 0) {
3010 if (BIO_read_filename(in, fp) <= 0) {
William Lallemand786188f2019-10-15 10:05:37 +02003011 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003012 *err ? *err : "", fp);
3013 ret = 1;
3014 goto end;
3015 }
3016
3017 issuer = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
3018 if (!issuer) {
William Lallemand786188f2019-10-15 10:05:37 +02003019 memprintf(err, "%s '%s' is present but cannot be read or parsed'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003020 *err ? *err : "", fp);
3021 ret = 1;
3022 goto end;
3023 }
3024
3025 if (X509_check_issued(ckch->ocsp_issuer, ckch->cert) != X509_V_OK) {
William Lallemand786188f2019-10-15 10:05:37 +02003026 memprintf(err, "%s '%s' is not an issuer'.\n",
William Lallemand246c0242019-10-11 08:59:13 +02003027 *err ? *err : "", fp);
3028 ret = 1;
3029 goto end;
3030 }
3031 } else {
3032 memprintf(err, "%sNo issuer found, cannot use the OCSP response'.\n",
3033 *err ? *err : "");
3034 ret = 1;
3035 goto end;
3036 }
3037 }
3038 }
3039
yanbzhu488a4d22015-12-01 15:16:07 -05003040 ret = 0;
3041
3042end:
3043
3044 ERR_clear_error();
William Lallemandf11365b2019-09-19 14:25:58 +02003045 if (in && !buf)
yanbzhu488a4d22015-12-01 15:16:07 -05003046 BIO_free(in);
3047
3048 /* Something went wrong in one of the reads */
3049 if (ret != 0)
3050 ssl_sock_free_cert_key_and_chain_contents(ckch);
3051
3052 return ret;
3053}
3054
3055/* Loads the info in ckch into ctx
Emeric Bruna96b5822019-10-17 13:25:14 +02003056 * Returns a bitfield containing the flags:
3057 * ERR_FATAL in any fatal error case
3058 * ERR_ALERT if the reason of the error is available in err
3059 * ERR_WARN if a warning is available into err
3060 * The value 0 means there is no error nor warning and
3061 * the operation succeed.
yanbzhu488a4d22015-12-01 15:16:07 -05003062 */
3063static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3064{
Emeric Bruna96b5822019-10-17 13:25:14 +02003065 int errcode = 0;
3066
yanbzhu488a4d22015-12-01 15:16:07 -05003067 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3068 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3069 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003070 errcode |= ERR_ALERT | ERR_FATAL;
3071 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003072 }
3073
3074 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3075 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3076 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003077 errcode |= ERR_ALERT | ERR_FATAL;
3078 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003079 }
3080
yanbzhu488a4d22015-12-01 15:16:07 -05003081 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003082#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003083 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3084 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3085 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003086 errcode |= ERR_ALERT | ERR_FATAL;
3087 goto end;
yanbzhu488a4d22015-12-01 15:16:07 -05003088 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003089#else
3090 { /* legacy compat (< openssl 1.0.2) */
3091 X509 *ca;
3092 while ((ca = sk_X509_shift(ckch->chain)))
3093 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3094 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3095 err && *err ? *err : "", path);
3096 X509_free(ca);
Emeric Bruna96b5822019-10-17 13:25:14 +02003097 errcode |= ERR_ALERT | ERR_FATAL;
3098 goto end;
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003099 }
3100 }
3101#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003102
William Lallemandfa892222019-07-23 16:06:08 +02003103#ifndef OPENSSL_NO_DH
3104 /* store a NULL pointer to indicate we have not yet loaded
3105 a custom DH param file */
3106 if (ssl_dh_ptr_index >= 0) {
3107 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3108 }
3109
Emeric Bruna96b5822019-10-17 13:25:14 +02003110 if (ssl_sock_load_dh_params(ctx, ckch, err) < 0) {
William Lallemandfa892222019-07-23 16:06:08 +02003111 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3112 err && *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003113 errcode |= ERR_ALERT | ERR_FATAL;
3114 goto end;
William Lallemandfa892222019-07-23 16:06:08 +02003115 }
3116#endif
3117
William Lallemanda17f4112019-10-10 15:16:44 +02003118#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3119 if (sctl_ex_index >= 0 && ckch->sctl) {
3120 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3121 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3122 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003123 errcode |= ERR_ALERT | ERR_FATAL;
3124 goto end;
William Lallemanda17f4112019-10-10 15:16:44 +02003125 }
3126 }
3127#endif
3128
William Lallemand4a660132019-10-14 14:51:41 +02003129#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003130 /* Load OCSP Info into context */
3131 if (ckch->ocsp_response) {
3132 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3133 if (err)
3134 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",
3135 *err ? *err : "", path);
Emeric Bruna96b5822019-10-17 13:25:14 +02003136 errcode |= ERR_ALERT | ERR_FATAL;
3137 goto end;
William Lallemand246c0242019-10-11 08:59:13 +02003138 }
3139 }
William Lallemand246c0242019-10-11 08:59:13 +02003140#endif
3141
Emeric Bruna96b5822019-10-17 13:25:14 +02003142 end:
3143 return errcode;
yanbzhu488a4d22015-12-01 15:16:07 -05003144}
3145
William Lallemandc4ecddf2019-07-31 16:50:08 +02003146#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003147
William Lallemand28a8fce2019-10-04 17:36:55 +02003148static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003149{
3150 struct sni_keytype *s_kt = NULL;
3151 struct ebmb_node *node;
3152 int i;
3153
3154 for (i = 0; i < trash.size; i++) {
3155 if (!str[i])
3156 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003157 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003158 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003159 trash.area[i] = 0;
3160 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003161 if (!node) {
3162 /* CN not found in tree */
3163 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3164 /* Using memcpy here instead of strncpy.
3165 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3166 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3167 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003168 if (!s_kt)
3169 return -1;
3170
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003171 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003172 s_kt->keytypes = 0;
3173 ebst_insert(sni_keytypes, &s_kt->name);
3174 } else {
3175 /* CN found in tree */
3176 s_kt = container_of(node, struct sni_keytype, name);
3177 }
3178
3179 /* Mark that this CN has the keytype of key_index via keytypes mask */
3180 s_kt->keytypes |= 1<<key_index;
3181
William Lallemand28a8fce2019-10-04 17:36:55 +02003182 return 0;
3183
yanbzhu08ce6ab2015-12-02 13:01:29 -05003184}
3185
William Lallemandc4ecddf2019-07-31 16:50:08 +02003186#endif
3187
William Lallemand36b84632019-07-18 19:28:17 +02003188/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003189 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003190 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003191static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003192{
3193 struct ebmb_node *eb;
3194
William Lallemande3af8fb2019-10-08 11:36:53 +02003195 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003196 if (!eb)
3197 return NULL;
3198
William Lallemande3af8fb2019-10-08 11:36:53 +02003199 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003200}
3201
3202/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003203 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003204 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003205static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003206{
William Lallemande3af8fb2019-10-08 11:36:53 +02003207 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003208
William Lallemande3af8fb2019-10-08 11:36:53 +02003209 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3210 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003211 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3212 goto end;
3213 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003214 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003215
William Lallemande3af8fb2019-10-08 11:36:53 +02003216 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003217 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3218 goto end;
3219 }
3220
William Lallemand9117de92019-10-04 00:29:42 +02003221 LIST_INIT(&ckchs->ckch_inst);
3222
William Lallemand36b84632019-07-18 19:28:17 +02003223 if (!multi) {
3224
William Lallemandf11365b2019-09-19 14:25:58 +02003225 if (ssl_sock_load_crt_file_into_ckch(path, NULL, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003226 goto end;
3227
William Lallemande3af8fb2019-10-08 11:36:53 +02003228 /* insert into the ckchs tree */
3229 memcpy(ckchs->path, path, strlen(path) + 1);
3230 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003231 } else {
3232 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003233#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3234 char fp[MAXPATHLEN+1] = {0};
3235 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003236
3237 /* Load all possible certs and keys */
3238 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3239 struct stat buf;
3240 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3241 if (stat(fp, &buf) == 0) {
William Lallemandf11365b2019-09-19 14:25:58 +02003242 if (ssl_sock_load_crt_file_into_ckch(fp, NULL, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003243 goto end;
3244 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003245 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003246 }
3247 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003248#endif
William Lallemand36b84632019-07-18 19:28:17 +02003249
3250 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003251 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003252 goto end;
3253 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003254 /* insert into the ckchs tree */
3255 memcpy(ckchs->path, path, strlen(path) + 1);
3256 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003257 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003258 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003259
William Lallemand36b84632019-07-18 19:28:17 +02003260end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003261 if (ckchs) {
3262 free(ckchs->ckch);
3263 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003264 }
3265
William Lallemande3af8fb2019-10-08 11:36:53 +02003266 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003267
3268 return NULL;
3269}
3270
William Lallemandc4ecddf2019-07-31 16:50:08 +02003271#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3272
William Lallemand36b84632019-07-18 19:28:17 +02003273/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003274 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003275 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003276 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3277 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003278 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003279 *
Emeric Brun054563d2019-10-17 13:16:58 +02003280 * Returns a bitfield containing the flags:
3281 * ERR_FATAL in any fatal error case
3282 * ERR_ALERT if the reason of the error is available in err
3283 * ERR_WARN if a warning is available into err
William Lallemand36b84632019-07-18 19:28:17 +02003284 *
3285 * TODO: This function shouldn't access files anymore, sctl and ocsp file access
3286 * should be migrated to the ssl_sock_load_crt_file_into_ckch() function
yanbzhu08ce6ab2015-12-02 13:01:29 -05003287 */
Emeric Brun054563d2019-10-17 13:16:58 +02003288static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3289 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3290 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003291{
William Lallemand36b84632019-07-18 19:28:17 +02003292 int i = 0, n = 0;
3293 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003294 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003295 struct ebmb_node *node;
3296 struct ebmb_node *next;
3297 /* Array of SSL_CTX pointers corresponding to each possible combo
3298 * of keytypes
3299 */
3300 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
Emeric Brun054563d2019-10-17 13:16:58 +02003301 int errcode = 0;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003302 X509_NAME *xname = NULL;
3303 char *str = NULL;
3304#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3305 STACK_OF(GENERAL_NAME) *names = NULL;
3306#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003307 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003308
Emeric Brun054563d2019-10-17 13:16:58 +02003309 *ckchi = NULL;
3310
William Lallemande3af8fb2019-10-08 11:36:53 +02003311 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003312 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3313 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003314 return ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003315 }
3316
3317 ckch_inst = ckch_inst_new();
3318 if (!ckch_inst) {
3319 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3320 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003321 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003322 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003323 }
3324
William Lallemande3af8fb2019-10-08 11:36:53 +02003325 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003326
William Lallemand150bfa82019-09-19 17:12:49 +02003327 /* at least one of the instances is using filters during the config
3328 * parsing, that's ok to inherit this during loading on CLI */
3329 ckchs->filters = !!fcount;
3330
yanbzhu08ce6ab2015-12-02 13:01:29 -05003331 /* Process each ckch and update keytypes for each CN/SAN
3332 * for example, if CN/SAN www.a.com is associated with
3333 * certs with keytype 0 and 2, then at the end of the loop,
3334 * www.a.com will have:
3335 * keyindex = 0 | 1 | 4 = 5
3336 */
3337 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003338 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003339
3340 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3341 continue;
3342
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003343 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003344 for (i = 0; i < fcount; i++) {
3345 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3346 if (ret < 0) {
3347 memprintf(err, "%sunable to allocate SSL context.\n",
3348 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003349 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003350 goto end;
3351 }
3352 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003353 } else {
3354 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3355 * so the line that contains logic is marked via comments
3356 */
3357 xname = X509_get_subject_name(certs_and_keys[n].cert);
3358 i = -1;
3359 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3360 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003361 ASN1_STRING *value;
3362 value = X509_NAME_ENTRY_get_data(entry);
3363 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003364 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003365 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003366
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003367 OPENSSL_free(str);
3368 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003369 if (ret < 0) {
3370 memprintf(err, "%sunable to allocate SSL context.\n",
3371 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003372 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003373 goto end;
3374 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003375 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003376 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003377
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003378 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003379#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003380 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3381 if (names) {
3382 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3383 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003384
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003385 if (name->type == GEN_DNS) {
3386 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3387 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003388 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003389
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003390 OPENSSL_free(str);
3391 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003392 if (ret < 0) {
3393 memprintf(err, "%sunable to allocate SSL context.\n",
3394 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003395 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003396 goto end;
3397 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003398 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003399 }
3400 }
3401 }
3402 }
3403#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3404 }
3405
3406 /* If no files found, return error */
3407 if (eb_is_empty(&sni_keytypes_map)) {
3408 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3409 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003410 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003411 goto end;
3412 }
3413
3414 /* We now have a map of CN/SAN to keytypes that are loaded in
3415 * Iterate through the map to create the SSL_CTX's (if needed)
3416 * and add each CTX to the SNI tree
3417 *
3418 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003419 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003420 * combination is denoted by the key in the map. Each key
3421 * has a value between 1 and 2^n - 1. Conveniently, the array
3422 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3423 * entry in the array to correspond to the unique combo (key)
3424 * associated with i. This unique key combo (i) will be associated
3425 * with combos[i-1]
3426 */
3427
3428 node = ebmb_first(&sni_keytypes_map);
3429 while (node) {
3430 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003431 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003432 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003433
3434 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3435 i = container_of(node, struct sni_keytype, name)->keytypes;
3436 cur_ctx = key_combos[i-1].ctx;
3437
3438 if (cur_ctx == NULL) {
3439 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003440 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003441 if (cur_ctx == NULL) {
3442 memprintf(err, "%sunable to allocate SSL context.\n",
3443 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003444 errcode |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003445 goto end;
3446 }
3447
yanbzhube2774d2015-12-10 15:07:30 -05003448 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003449 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3450 if (i & (1<<n)) {
3451 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003452 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
Emeric Bruna96b5822019-10-17 13:25:14 +02003453 errcode |= ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err);
3454 if (errcode & ERR_CODE)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003455 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003456 }
3457 }
3458
yanbzhu08ce6ab2015-12-02 13:01:29 -05003459 /* Update key_combos */
3460 key_combos[i-1].ctx = cur_ctx;
3461 }
3462
3463 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003464
William Lallemand1d29c742019-10-04 00:53:29 +02003465 key_combos[i-1].order = ckch_inst_add_cert_sni(cur_ctx, ckch_inst, bind_conf, ssl_conf,
William Lallemandfe49bb32019-10-03 23:46:33 +02003466 kinfo, str, key_combos[i-1].order);
3467 if (key_combos[i-1].order < 0) {
3468 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003469 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandfe49bb32019-10-03 23:46:33 +02003470 goto end;
3471 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003472 node = ebmb_next(node);
3473 }
3474
3475
3476 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3477 if (!bind_conf->default_ctx) {
3478 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3479 if (key_combos[i].ctx) {
3480 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003481 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003482 break;
3483 }
3484 }
3485 }
3486
William Lallemand614ca0d2019-10-07 13:52:11 +02003487 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003488 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003489end:
3490
3491 if (names)
3492 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3493
yanbzhu08ce6ab2015-12-02 13:01:29 -05003494 node = ebmb_first(&sni_keytypes_map);
3495 while (node) {
3496 next = ebmb_next(node);
3497 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003498 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003499 node = next;
3500 }
3501
Emeric Brun054563d2019-10-17 13:16:58 +02003502 if (errcode & ERR_CODE && ckch_inst) {
William Lallemand0c6d12f2019-10-04 18:38:51 +02003503 struct sni_ctx *sc0, *sc0b;
3504
3505 /* free the SSL_CTX in case of error */
3506 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3507 if (key_combos[i].ctx)
3508 SSL_CTX_free(key_combos[i].ctx);
3509 }
3510
3511 /* free the sni_ctx in case of error */
3512 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3513
3514 ebmb_delete(&sc0->name);
3515 LIST_DEL(&sc0->by_ckch_inst);
3516 free(sc0);
3517 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003518 free(ckch_inst);
3519 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003520 }
3521
Emeric Brun054563d2019-10-17 13:16:58 +02003522 *ckchi = ckch_inst;
3523 return errcode;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003524}
3525#else
3526/* This is a dummy, that just logs an error and returns error */
Emeric Brun054563d2019-10-17 13:16:58 +02003527static int ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
3528 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3529 char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003530{
3531 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3532 err && *err ? *err : "", path, strerror(errno));
Emeric Brun054563d2019-10-17 13:16:58 +02003533 return ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003534}
3535
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003536#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003537
William Lallemand614ca0d2019-10-07 13:52:11 +02003538/*
3539 * This function allocate a ckch_inst and create its snis
Emeric Brun054563d2019-10-17 13:16:58 +02003540 *
3541 * Returns a bitfield containing the flags:
3542 * ERR_FATAL in any fatal error case
3543 * ERR_ALERT if the reason of the error is available in err
3544 * ERR_WARN if a warning is available into err
William Lallemand614ca0d2019-10-07 13:52:11 +02003545 */
Emeric Brun054563d2019-10-17 13:16:58 +02003546static int ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3547 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, struct ckch_inst **ckchi, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003548{
William Lallemandc9402072019-05-15 15:33:54 +02003549 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003550 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003551 int order = 0;
3552 X509_NAME *xname;
3553 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003554 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003555 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003556#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3557 STACK_OF(GENERAL_NAME) *names;
3558#endif
William Lallemand36b84632019-07-18 19:28:17 +02003559 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003560 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003561 int errcode = 0;
3562
3563 *ckchi = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003564
William Lallemande3af8fb2019-10-08 11:36:53 +02003565 if (!ckchs || !ckchs->ckch)
Emeric Brun054563d2019-10-17 13:16:58 +02003566 return ERR_FATAL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003567
William Lallemande3af8fb2019-10-08 11:36:53 +02003568 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003569
William Lallemand150bfa82019-09-19 17:12:49 +02003570 /* at least one of the instances is using filters during the config
3571 * parsing, that's ok to inherit this during loading on CLI */
3572 ckchs->filters = !!fcount;
3573
William Lallemandc9402072019-05-15 15:33:54 +02003574 ctx = SSL_CTX_new(SSLv23_server_method());
3575 if (!ctx) {
3576 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3577 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003578 errcode |= ERR_ALERT | ERR_FATAL;
3579 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003580 }
3581
Emeric Bruna96b5822019-10-17 13:25:14 +02003582 errcode |= ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err);
3583 if (errcode & ERR_CODE)
William Lallemand614ca0d2019-10-07 13:52:11 +02003584 goto error;
William Lallemand614ca0d2019-10-07 13:52:11 +02003585
3586 ckch_inst = ckch_inst_new();
3587 if (!ckch_inst) {
3588 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3589 err && *err ? *err : "", path);
Emeric Brun054563d2019-10-17 13:16:58 +02003590 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003591 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003592 }
3593
William Lallemand36b84632019-07-18 19:28:17 +02003594 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003595 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003596 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003597 switch(EVP_PKEY_base_id(pkey)) {
3598 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003599 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003600 break;
3601 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003602 kinfo.sig = TLSEXT_signature_ecdsa;
3603 break;
3604 case EVP_PKEY_DSA:
3605 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003606 break;
3607 }
3608 EVP_PKEY_free(pkey);
3609 }
3610
Emeric Brun50bcecc2013-04-22 13:05:23 +02003611 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003612 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003613 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, sni_filter[fcount], order);
William Lallemandfe49bb32019-10-03 23:46:33 +02003614 if (order < 0) {
3615 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003616 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003617 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003618 }
3619 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003620 }
3621 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003622#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003623 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003624 if (names) {
3625 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3626 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3627 if (name->type == GEN_DNS) {
3628 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003629 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003630 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003631 if (order < 0) {
3632 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003633 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003634 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003635 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003636 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003637 }
3638 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003639 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003640 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003641#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02003642 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003643 i = -1;
3644 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3645 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003646 ASN1_STRING *value;
3647
3648 value = X509_NAME_ENTRY_get_data(entry);
3649 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003650 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003651 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003652 if (order < 0) {
3653 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003654 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003655 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003656 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003657 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003658 }
3659 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003660 /* we must not free the SSL_CTX anymore below, since it's already in
3661 * the tree, so it will be discovered and cleaned in time.
3662 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003663
Emeric Brunfc0421f2012-09-07 17:30:07 +02003664#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003665 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003666 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3667 err && *err ? *err : "");
Emeric Brun054563d2019-10-17 13:16:58 +02003668 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemandd9199372019-10-04 15:37:05 +02003669 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003670 }
3671#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003672 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003673 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003674 bind_conf->default_ssl_conf = ssl_conf;
3675 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003676
William Lallemand9117de92019-10-04 00:29:42 +02003677 /* everything succeed, the ckch instance can be used */
3678 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003679 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02003680
Emeric Brun054563d2019-10-17 13:16:58 +02003681 *ckchi = ckch_inst;
3682 return errcode;
William Lallemandd9199372019-10-04 15:37:05 +02003683
3684error:
3685 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02003686 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02003687 struct sni_ctx *sc0, *sc0b;
3688
3689 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3690
3691 ebmb_delete(&sc0->name);
3692 LIST_DEL(&sc0->by_ckch_inst);
3693 free(sc0);
3694 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003695 free(ckch_inst);
3696 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02003697 }
3698 /* We only created 1 SSL_CTX so we can free it there */
3699 SSL_CTX_free(ctx);
3700
Emeric Brun054563d2019-10-17 13:16:58 +02003701 return errcode;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003702}
3703
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003704/* Returns a set of ERR_* flags possibly with an error in <err>. */
William Lallemand614ca0d2019-10-07 13:52:11 +02003705static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
3706 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3707 char **sni_filter, int fcount, char **err)
3708{
3709 struct ckch_inst *ckch_inst = NULL;
Emeric Brun054563d2019-10-17 13:16:58 +02003710 int errcode = 0;
William Lallemand614ca0d2019-10-07 13:52:11 +02003711
3712 /* we found the ckchs in the tree, we can use it directly */
3713 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02003714 errcode |= ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02003715 else
Emeric Brun054563d2019-10-17 13:16:58 +02003716 errcode |= ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, &ckch_inst, err);
William Lallemand614ca0d2019-10-07 13:52:11 +02003717
Emeric Brun054563d2019-10-17 13:16:58 +02003718 if (errcode & ERR_CODE)
3719 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003720
3721 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
3722
3723 /* succeed, add the instance to the ckch_store's list of instance */
3724 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
Emeric Brun054563d2019-10-17 13:16:58 +02003725 return errcode;
William Lallemand614ca0d2019-10-07 13:52:11 +02003726}
3727
3728
Willy Tarreaubbc91962019-10-16 16:42:19 +02003729/* Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau03209342016-12-22 17:08:28 +01003730int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003731{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003732 struct dirent **de_list;
3733 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003734 DIR *dir;
3735 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003736 char *end;
3737 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003738 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003739 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003740#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003741 int is_bundle;
3742 int j;
3743#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003744 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003745 /* we found the ckchs in the tree, we can use it directly */
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003746 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand6af03992019-07-23 15:00:54 +02003747 }
3748
yanbzhu08ce6ab2015-12-02 13:01:29 -05003749 if (stat(path, &buf) == 0) {
3750 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02003751 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003752 ckchs = ckchs_load_cert_file(path, 0, err);
3753 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003754 return ERR_ALERT | ERR_FATAL;
3755
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003756 return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003757 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003758
yanbzhu08ce6ab2015-12-02 13:01:29 -05003759 /* strip trailing slashes, including first one */
3760 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3761 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003762
yanbzhu08ce6ab2015-12-02 13:01:29 -05003763 n = scandir(path, &de_list, 0, alphasort);
3764 if (n < 0) {
3765 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3766 err && *err ? *err : "", path, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003767 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003768 }
3769 else {
3770 for (i = 0; i < n; i++) {
3771 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003772
yanbzhu08ce6ab2015-12-02 13:01:29 -05003773 end = strrchr(de->d_name, '.');
3774 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3775 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003776
yanbzhu08ce6ab2015-12-02 13:01:29 -05003777 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3778 if (stat(fp, &buf) != 0) {
3779 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3780 err && *err ? *err : "", fp, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003781 cfgerr |= ERR_ALERT | ERR_FATAL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003782 goto ignore_entry;
3783 }
3784 if (!S_ISREG(buf.st_mode))
3785 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003786
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003787#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003788 is_bundle = 0;
3789 /* Check if current entry in directory is part of a multi-cert bundle */
3790
3791 if (end) {
3792 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3793 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3794 is_bundle = 1;
3795 break;
3796 }
3797 }
3798
3799 if (is_bundle) {
3800 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3801 int dp_len;
3802
3803 dp_len = end - de->d_name;
3804 snprintf(dp, dp_len + 1, "%s", de->d_name);
3805
3806 /* increment i and free de until we get to a non-bundle cert
3807 * Note here that we look at de_list[i + 1] before freeing de
3808 * this is important since ignore_entry will free de
3809 */
3810 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3811 free(de);
3812 i++;
3813 de = de_list[i];
3814 }
3815
3816 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
William Lallemande3af8fb2019-10-08 11:36:53 +02003817 if ((ckchs = ckchs_lookup(fp)) == NULL)
3818 ckchs = ckchs_load_cert_file(fp, 1, err);
3819 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003820 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003821 else
3822 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003823 /* Successfully processed the bundle */
3824 goto ignore_entry;
3825 }
3826 }
3827
3828#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003829 if ((ckchs = ckchs_lookup(fp)) == NULL)
3830 ckchs = ckchs_load_cert_file(fp, 0, err);
3831 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003832 cfgerr |= ERR_ALERT | ERR_FATAL;
William Lallemand614ca0d2019-10-07 13:52:11 +02003833 else
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003834 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003835
yanbzhu08ce6ab2015-12-02 13:01:29 -05003836ignore_entry:
3837 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003838 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003839 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003840 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003841 closedir(dir);
3842 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003843 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003844
William Lallemande3af8fb2019-10-08 11:36:53 +02003845 ckchs = ckchs_load_cert_file(path, 1, err);
3846 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02003847 return ERR_ALERT | ERR_FATAL;
3848
Willy Tarreau8c5414a2019-10-16 17:06:25 +02003849 cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003850
Emeric Brunfc0421f2012-09-07 17:30:07 +02003851 return cfgerr;
3852}
3853
Thierry Fournier383085f2013-01-24 14:15:43 +01003854/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3855 * done once. Zero is returned if the operation fails. No error is returned
3856 * if the random is said as not implemented, because we expect that openssl
3857 * will use another method once needed.
3858 */
3859static int ssl_initialize_random()
3860{
3861 unsigned char random;
3862 static int random_initialized = 0;
3863
3864 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3865 random_initialized = 1;
3866
3867 return random_initialized;
3868}
3869
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003870/* release ssl bind conf */
3871void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003872{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003873 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003874#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003875 free(conf->npn_str);
3876 conf->npn_str = NULL;
3877#endif
3878#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3879 free(conf->alpn_str);
3880 conf->alpn_str = NULL;
3881#endif
3882 free(conf->ca_file);
3883 conf->ca_file = NULL;
3884 free(conf->crl_file);
3885 conf->crl_file = NULL;
3886 free(conf->ciphers);
3887 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003888#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003889 free(conf->ciphersuites);
3890 conf->ciphersuites = NULL;
3891#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003892 free(conf->curves);
3893 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003894 free(conf->ecdhe);
3895 conf->ecdhe = NULL;
3896 }
3897}
3898
Willy Tarreaubbc91962019-10-16 16:42:19 +02003899/* Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003900int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3901{
3902 char thisline[CRT_LINESIZE];
3903 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003904 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003905 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003906 int linenum = 0;
3907 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003908 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003909
Willy Tarreauad1731d2013-04-02 17:35:58 +02003910 if ((f = fopen(file, "r")) == NULL) {
3911 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Willy Tarreaubbc91962019-10-16 16:42:19 +02003912 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003913 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003914
3915 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003916 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003917 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003918 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003919 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003920 char *crt_path;
3921 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003922
3923 linenum++;
3924 end = line + strlen(line);
3925 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3926 /* Check if we reached the limit and the last char is not \n.
3927 * Watch out for the last line without the terminating '\n'!
3928 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003929 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3930 linenum, file, (int)sizeof(thisline)-1);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003931 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003932 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003933 }
3934
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003935 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003936 newarg = 1;
3937 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003938 if (*line == '#' || *line == '\n' || *line == '\r') {
3939 /* end of string, end of loop */
3940 *line = 0;
3941 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003942 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003943 newarg = 1;
3944 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003945 } else if (*line == '[') {
3946 if (ssl_b) {
3947 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003948 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003949 break;
3950 }
3951 if (!arg) {
3952 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003953 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003954 break;
3955 }
3956 ssl_b = arg;
3957 newarg = 1;
3958 *line = 0;
3959 } else if (*line == ']') {
3960 if (ssl_e) {
3961 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003962 cfgerr |= ERR_ALERT | ERR_FATAL;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003963 break;
3964 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003965 if (!ssl_b) {
3966 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003967 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003968 break;
3969 }
3970 ssl_e = arg;
3971 newarg = 1;
3972 *line = 0;
3973 } else if (newarg) {
3974 if (arg == MAX_CRT_ARGS) {
3975 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003976 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003977 break;
3978 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003979 newarg = 0;
3980 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003981 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003982 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003983 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003984 if (cfgerr)
3985 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003986 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003987
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003988 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003989 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003990 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003991
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003992 crt_path = args[0];
3993 if (*crt_path != '/' && global_ssl.crt_base) {
3994 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3995 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3996 crt_path, linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02003997 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003998 break;
3999 }
4000 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
4001 crt_path = path;
4002 }
4003
4004 ssl_conf = calloc(1, sizeof *ssl_conf);
4005 cur_arg = ssl_b ? ssl_b : 1;
4006 while (cur_arg < ssl_e) {
4007 newarg = 0;
4008 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
4009 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
4010 newarg = 1;
Willy Tarreaubbc91962019-10-16 16:42:19 +02004011 cfgerr |= ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004012 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
4013 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
4014 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004015 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004016 }
4017 cur_arg += 1 + ssl_bind_kws[i].skip;
4018 break;
4019 }
4020 }
4021 if (!cfgerr && !newarg) {
4022 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
4023 args[cur_arg], linenum, file);
Willy Tarreaubbc91962019-10-16 16:42:19 +02004024 cfgerr |= ERR_ALERT | ERR_FATAL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004025 break;
4026 }
4027 }
Willy Tarreaubbc91962019-10-16 16:42:19 +02004028
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004029 if (cfgerr) {
4030 ssl_sock_free_ssl_conf(ssl_conf);
4031 free(ssl_conf);
4032 ssl_conf = NULL;
4033 break;
4034 }
4035
William Lallemande3af8fb2019-10-08 11:36:53 +02004036 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004037 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004038 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004039 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004040 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004041 }
4042
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004043 if (!ckchs)
Willy Tarreaubbc91962019-10-16 16:42:19 +02004044 cfgerr |= ERR_ALERT | ERR_FATAL;
Willy Tarreau8c5414a2019-10-16 17:06:25 +02004045 else
4046 cfgerr |= ssl_sock_load_ckchs(crt_path, ckchs, bind_conf, ssl_conf, &args[cur_arg], arg - cur_arg - 1, err);
William Lallemandeed4bf22019-10-10 11:38:13 +02004047
Willy Tarreauad1731d2013-04-02 17:35:58 +02004048 if (cfgerr) {
4049 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004050 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004051 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004052 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004053 fclose(f);
4054 return cfgerr;
4055}
4056
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004057/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004058static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004059ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004060{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004061 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004062 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004063 SSL_OP_ALL | /* all known workarounds for bugs */
4064 SSL_OP_NO_SSLv2 |
4065 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004066 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004067 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004068 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004069 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004070 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004071 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004072 SSL_MODE_ENABLE_PARTIAL_WRITE |
4073 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004074 SSL_MODE_RELEASE_BUFFERS |
4075 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004076 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004077 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004078 int flags = MC_SSL_O_ALL;
4079 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004080
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004081 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004082 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004083
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004084 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004085 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4086 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4087 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004088 else
4089 flags = conf_ssl_methods->flags;
4090
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004091 min = conf_ssl_methods->min;
4092 max = conf_ssl_methods->max;
4093 /* start with TLSv10 to remove SSLv3 per default */
4094 if (!min && (!max || max >= CONF_TLSV10))
4095 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004096 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004097 if (min)
4098 flags |= (methodVersions[min].flag - 1);
4099 if (max)
4100 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004101 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004102 min = max = CONF_TLSV_NONE;
4103 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004104 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004105 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004106 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004107 if (min) {
4108 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004109 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4110 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4111 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4112 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004113 hole = 0;
4114 }
4115 max = i;
4116 }
4117 else {
4118 min = max = i;
4119 }
4120 }
4121 else {
4122 if (min)
4123 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004124 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004125 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004126 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4127 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004128 cfgerr += 1;
4129 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004130 /* save real min/max in bind_conf */
4131 conf_ssl_methods->min = min;
4132 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004133
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004134#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004135 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004136 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004137 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004138 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004139 else
4140 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4141 if (flags & methodVersions[i].flag)
4142 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004143#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004144 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004145 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4146 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004147#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004148
4149 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4150 options |= SSL_OP_NO_TICKET;
4151 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4152 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004153
4154#ifdef SSL_OP_NO_RENEGOTIATION
4155 options |= SSL_OP_NO_RENEGOTIATION;
4156#endif
4157
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004158 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004159
Willy Tarreau5db847a2019-05-09 14:13:35 +02004160#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004161 if (global_ssl.async)
4162 mode |= SSL_MODE_ASYNC;
4163#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004164 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004165 if (global_ssl.life_time)
4166 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004167
4168#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4169#ifdef OPENSSL_IS_BORINGSSL
4170 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4171 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004172#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004173 if (bind_conf->ssl_conf.early_data) {
4174 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4175 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4176 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004177 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4178 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004179#else
4180 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004181#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004182 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004183#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004184 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004185}
4186
William Lallemand4f45bb92017-10-30 20:08:51 +01004187
4188static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4189{
4190 if (first == block) {
4191 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4192 if (first->len > 0)
4193 sh_ssl_sess_tree_delete(sh_ssl_sess);
4194 }
4195}
4196
4197/* return first block from sh_ssl_sess */
4198static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4199{
4200 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4201
4202}
4203
4204/* store a session into the cache
4205 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4206 * data: asn1 encoded session
4207 * data_len: asn1 encoded session length
4208 * Returns 1 id session was stored (else 0)
4209 */
4210static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4211{
4212 struct shared_block *first;
4213 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4214
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004215 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004216 if (!first) {
4217 /* Could not retrieve enough free blocks to store that session */
4218 return 0;
4219 }
4220
4221 /* STORE the key in the first elem */
4222 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4223 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4224 first->len = sizeof(struct sh_ssl_sess_hdr);
4225
4226 /* it returns the already existing node
4227 or current node if none, never returns null */
4228 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4229 if (oldsh_ssl_sess != sh_ssl_sess) {
4230 /* NOTE: Row couldn't be in use because we lock read & write function */
4231 /* release the reserved row */
4232 shctx_row_dec_hot(ssl_shctx, first);
4233 /* replace the previous session already in the tree */
4234 sh_ssl_sess = oldsh_ssl_sess;
4235 /* ignore the previous session data, only use the header */
4236 first = sh_ssl_sess_first_block(sh_ssl_sess);
4237 shctx_row_inc_hot(ssl_shctx, first);
4238 first->len = sizeof(struct sh_ssl_sess_hdr);
4239 }
4240
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004241 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004242 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004243 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004244 }
4245
4246 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004247
4248 return 1;
4249}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004250
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004251/* SSL callback used when a new session is created while connecting to a server */
4252static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4253{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004254 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004255 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004256
Willy Tarreau07d94e42018-09-20 10:57:52 +02004257 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004258
Olivier Houcharde6060c52017-11-16 17:42:52 +01004259 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4260 int len;
4261 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004262
Olivier Houcharde6060c52017-11-16 17:42:52 +01004263 len = i2d_SSL_SESSION(sess, NULL);
4264 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4265 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4266 } else {
4267 free(s->ssl_ctx.reused_sess[tid].ptr);
4268 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4269 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4270 }
4271 if (s->ssl_ctx.reused_sess[tid].ptr) {
4272 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4273 &ptr);
4274 }
4275 } else {
4276 free(s->ssl_ctx.reused_sess[tid].ptr);
4277 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4278 }
4279
4280 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004281}
4282
Olivier Houcharde6060c52017-11-16 17:42:52 +01004283
William Lallemanded0b5ad2017-10-30 19:36:36 +01004284/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004285int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004286{
4287 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4288 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4289 unsigned char *p;
4290 int data_len;
4291 unsigned int sid_length, sid_ctx_length;
4292 const unsigned char *sid_data;
4293 const unsigned char *sid_ctx_data;
4294
4295 /* Session id is already stored in to key and session id is known
4296 * so we dont store it to keep size.
4297 */
4298
4299 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4300 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4301 SSL_SESSION_set1_id(sess, sid_data, 0);
4302 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4303
4304 /* check if buffer is large enough for the ASN1 encoded session */
4305 data_len = i2d_SSL_SESSION(sess, NULL);
4306 if (data_len > SHSESS_MAX_DATA_LEN)
4307 goto err;
4308
4309 p = encsess;
4310
4311 /* process ASN1 session encoding before the lock */
4312 i2d_SSL_SESSION(sess, &p);
4313
4314 memcpy(encid, sid_data, sid_length);
4315 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4316 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4317
William Lallemanda3c77cf2017-10-30 23:44:40 +01004318 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004319 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004320 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004321 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004322err:
4323 /* reset original length values */
4324 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4325 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4326
4327 return 0; /* do not increment session reference count */
4328}
4329
4330/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004331SSL_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 +01004332{
William Lallemand4f45bb92017-10-30 20:08:51 +01004333 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004334 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4335 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004336 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004337 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004338
4339 global.shctx_lookups++;
4340
4341 /* allow the session to be freed automatically by openssl */
4342 *do_copy = 0;
4343
4344 /* tree key is zeros padded sessionid */
4345 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4346 memcpy(tmpkey, key, key_len);
4347 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4348 key = tmpkey;
4349 }
4350
4351 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004352 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004353
4354 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004355 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4356 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004357 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004358 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004359 global.shctx_misses++;
4360 return NULL;
4361 }
4362
William Lallemand4f45bb92017-10-30 20:08:51 +01004363 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4364 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004365
William Lallemand4f45bb92017-10-30 20:08:51 +01004366 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 +01004367
William Lallemanda3c77cf2017-10-30 23:44:40 +01004368 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004369
4370 /* decode ASN1 session */
4371 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004372 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004373 /* Reset session id and session id contenxt */
4374 if (sess) {
4375 SSL_SESSION_set1_id(sess, key, key_len);
4376 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4377 }
4378
4379 return sess;
4380}
4381
William Lallemand4f45bb92017-10-30 20:08:51 +01004382
William Lallemanded0b5ad2017-10-30 19:36:36 +01004383/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004384void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004385{
William Lallemand4f45bb92017-10-30 20:08:51 +01004386 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004387 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4388 unsigned int sid_length;
4389 const unsigned char *sid_data;
4390 (void)ctx;
4391
4392 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4393 /* tree key is zeros padded sessionid */
4394 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4395 memcpy(tmpkey, sid_data, sid_length);
4396 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4397 sid_data = tmpkey;
4398 }
4399
William Lallemanda3c77cf2017-10-30 23:44:40 +01004400 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004401
4402 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004403 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4404 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004405 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004406 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004407 }
4408
4409 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004410 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004411}
4412
4413/* Set session cache mode to server and disable openssl internal cache.
4414 * Set shared cache callbacks on an ssl context.
4415 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004416void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004417{
4418 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4419
4420 if (!ssl_shctx) {
4421 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4422 return;
4423 }
4424
4425 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4426 SSL_SESS_CACHE_NO_INTERNAL |
4427 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4428
4429 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004430 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4431 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4432 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004433}
4434
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004435int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4436{
4437 struct proxy *curproxy = bind_conf->frontend;
4438 int cfgerr = 0;
4439 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004440 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004441 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004442#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004443 const char *conf_ciphersuites;
4444#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004445 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004446
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004447 if (ssl_conf) {
4448 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4449 int i, min, max;
4450 int flags = MC_SSL_O_ALL;
4451
4452 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004453 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4454 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004455 if (min)
4456 flags |= (methodVersions[min].flag - 1);
4457 if (max)
4458 flags |= ~((methodVersions[max].flag << 1) - 1);
4459 min = max = CONF_TLSV_NONE;
4460 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4461 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4462 if (min)
4463 max = i;
4464 else
4465 min = max = i;
4466 }
4467 /* save real min/max */
4468 conf_ssl_methods->min = min;
4469 conf_ssl_methods->max = max;
4470 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004471 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4472 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004473 cfgerr += 1;
4474 }
4475 }
4476
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004477 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004478 case SSL_SOCK_VERIFY_NONE:
4479 verify = SSL_VERIFY_NONE;
4480 break;
4481 case SSL_SOCK_VERIFY_OPTIONAL:
4482 verify = SSL_VERIFY_PEER;
4483 break;
4484 case SSL_SOCK_VERIFY_REQUIRED:
4485 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4486 break;
4487 }
4488 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4489 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004490 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4491 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4492 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004493 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004494 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004495 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4496 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004497 cfgerr++;
4498 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004499 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4500 /* set CA names for client cert request, function returns void */
4501 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4502 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004503 }
Emeric Brun850efd52014-01-29 12:24:34 +01004504 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004505 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4506 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004507 cfgerr++;
4508 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004509#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004510 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004511 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4512
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004513 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004514 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4515 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004516 cfgerr++;
4517 }
Emeric Brun561e5742012-10-02 15:20:55 +02004518 else {
4519 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4520 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004521 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004522#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004523 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004524 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004525#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004526 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004527 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004528 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4529 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004530 cfgerr++;
4531 }
4532 }
4533#endif
4534
William Lallemand4f45bb92017-10-30 20:08:51 +01004535 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004536 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4537 if (conf_ciphers &&
4538 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004539 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4540 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004541 cfgerr++;
4542 }
4543
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004544#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004545 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4546 if (conf_ciphersuites &&
4547 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4548 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4549 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4550 cfgerr++;
4551 }
4552#endif
4553
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004554#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004555 /* If tune.ssl.default-dh-param has not been set,
4556 neither has ssl-default-dh-file and no static DH
4557 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004558 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004559 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004560 (ssl_dh_ptr_index == -1 ||
4561 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004562 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4563 const SSL_CIPHER * cipher = NULL;
4564 char cipher_description[128];
4565 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4566 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4567 which is not ephemeral DH. */
4568 const char dhe_description[] = " Kx=DH ";
4569 const char dhe_export_description[] = " Kx=DH(";
4570 int idx = 0;
4571 int dhe_found = 0;
4572 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004573
Remi Gacogne23d5d372014-10-10 17:04:26 +02004574 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004575
Remi Gacogne23d5d372014-10-10 17:04:26 +02004576 if (ssl) {
4577 ciphers = SSL_get_ciphers(ssl);
4578
4579 if (ciphers) {
4580 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4581 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4582 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4583 if (strstr(cipher_description, dhe_description) != NULL ||
4584 strstr(cipher_description, dhe_export_description) != NULL) {
4585 dhe_found = 1;
4586 break;
4587 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004588 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004589 }
4590 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004591 SSL_free(ssl);
4592 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004593 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004594
Lukas Tribus90132722014-08-18 00:56:33 +02004595 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004596 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 +02004597 }
4598
Willy Tarreauef934602016-12-22 23:12:01 +01004599 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004600 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004601
Willy Tarreauef934602016-12-22 23:12:01 +01004602 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004603 if (local_dh_1024 == NULL) {
4604 local_dh_1024 = ssl_get_dh_1024();
4605 }
Willy Tarreauef934602016-12-22 23:12:01 +01004606 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004607 if (local_dh_2048 == NULL) {
4608 local_dh_2048 = ssl_get_dh_2048();
4609 }
Willy Tarreauef934602016-12-22 23:12:01 +01004610 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004611 if (local_dh_4096 == NULL) {
4612 local_dh_4096 = ssl_get_dh_4096();
4613 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004614 }
4615 }
4616 }
4617#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004618
Emeric Brunfc0421f2012-09-07 17:30:07 +02004619 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004620#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004621 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004622#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004623
Bernard Spil13c53f82018-02-15 13:34:58 +01004624#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004625 ssl_conf_cur = NULL;
4626 if (ssl_conf && ssl_conf->npn_str)
4627 ssl_conf_cur = ssl_conf;
4628 else if (bind_conf->ssl_conf.npn_str)
4629 ssl_conf_cur = &bind_conf->ssl_conf;
4630 if (ssl_conf_cur)
4631 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004632#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004633#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004634 ssl_conf_cur = NULL;
4635 if (ssl_conf && ssl_conf->alpn_str)
4636 ssl_conf_cur = ssl_conf;
4637 else if (bind_conf->ssl_conf.alpn_str)
4638 ssl_conf_cur = &bind_conf->ssl_conf;
4639 if (ssl_conf_cur)
4640 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004641#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004642#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004643 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4644 if (conf_curves) {
4645 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004646 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4647 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004648 cfgerr++;
4649 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004650#if defined(SSL_CTX_set_ecdh_auto)
4651 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4652#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004653 }
4654#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004655#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004656 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004657 int i;
4658 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004659#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004660 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004661 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4662 NULL);
4663
4664 if (ecdhe == NULL) {
4665 SSL_CTX_set_dh_auto(ctx, 1);
4666 return cfgerr;
4667 }
4668#else
4669 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4670 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4671 ECDHE_DEFAULT_CURVE);
4672#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004673
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004674 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004675 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004676 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4677 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004678 cfgerr++;
4679 }
4680 else {
4681 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4682 EC_KEY_free(ecdh);
4683 }
4684 }
4685#endif
4686
Emeric Brunfc0421f2012-09-07 17:30:07 +02004687 return cfgerr;
4688}
4689
Evan Broderbe554312013-06-27 00:05:25 -07004690static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4691{
4692 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4693 size_t prefixlen, suffixlen;
4694
4695 /* Trivial case */
4696 if (strcmp(pattern, hostname) == 0)
4697 return 1;
4698
Evan Broderbe554312013-06-27 00:05:25 -07004699 /* The rest of this logic is based on RFC 6125, section 6.4.3
4700 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4701
Emeric Bruna848dae2013-10-08 11:27:28 +02004702 pattern_wildcard = NULL;
4703 pattern_left_label_end = pattern;
4704 while (*pattern_left_label_end != '.') {
4705 switch (*pattern_left_label_end) {
4706 case 0:
4707 /* End of label not found */
4708 return 0;
4709 case '*':
4710 /* If there is more than one wildcards */
4711 if (pattern_wildcard)
4712 return 0;
4713 pattern_wildcard = pattern_left_label_end;
4714 break;
4715 }
4716 pattern_left_label_end++;
4717 }
4718
4719 /* If it's not trivial and there is no wildcard, it can't
4720 * match */
4721 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004722 return 0;
4723
4724 /* Make sure all labels match except the leftmost */
4725 hostname_left_label_end = strchr(hostname, '.');
4726 if (!hostname_left_label_end
4727 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4728 return 0;
4729
4730 /* Make sure the leftmost label of the hostname is long enough
4731 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004732 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004733 return 0;
4734
4735 /* Finally compare the string on either side of the
4736 * wildcard */
4737 prefixlen = pattern_wildcard - pattern;
4738 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004739 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4740 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004741 return 0;
4742
4743 return 1;
4744}
4745
4746static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4747{
4748 SSL *ssl;
4749 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004750 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004751 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004752 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004753
4754 int depth;
4755 X509 *cert;
4756 STACK_OF(GENERAL_NAME) *alt_names;
4757 int i;
4758 X509_NAME *cert_subject;
4759 char *str;
4760
4761 if (ok == 0)
4762 return ok;
4763
4764 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004765 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004766 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004767
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004768 /* We're checking if the provided hostnames match the desired one. The
4769 * desired hostname comes from the SNI we presented if any, or if not
4770 * provided then it may have been explicitly stated using a "verifyhost"
4771 * directive. If neither is set, we don't care about the name so the
4772 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004773 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004774 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004775 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004776 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004777 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004778 if (!servername)
4779 return ok;
4780 }
Evan Broderbe554312013-06-27 00:05:25 -07004781
4782 /* We only need to verify the CN on the actual server cert,
4783 * not the indirect CAs */
4784 depth = X509_STORE_CTX_get_error_depth(ctx);
4785 if (depth != 0)
4786 return ok;
4787
4788 /* At this point, the cert is *not* OK unless we can find a
4789 * hostname match */
4790 ok = 0;
4791
4792 cert = X509_STORE_CTX_get_current_cert(ctx);
4793 /* It seems like this might happen if verify peer isn't set */
4794 if (!cert)
4795 return ok;
4796
4797 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4798 if (alt_names) {
4799 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4800 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4801 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004802#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004803 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4804#else
Evan Broderbe554312013-06-27 00:05:25 -07004805 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004806#endif
Evan Broderbe554312013-06-27 00:05:25 -07004807 ok = ssl_sock_srv_hostcheck(str, servername);
4808 OPENSSL_free(str);
4809 }
4810 }
4811 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004812 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004813 }
4814
4815 cert_subject = X509_get_subject_name(cert);
4816 i = -1;
4817 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4818 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004819 ASN1_STRING *value;
4820 value = X509_NAME_ENTRY_get_data(entry);
4821 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004822 ok = ssl_sock_srv_hostcheck(str, servername);
4823 OPENSSL_free(str);
4824 }
4825 }
4826
Willy Tarreau71d058c2017-07-26 20:09:56 +02004827 /* report the mismatch and indicate if SNI was used or not */
4828 if (!ok && !conn->err_code)
4829 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004830 return ok;
4831}
4832
Emeric Brun94324a42012-10-11 14:00:19 +02004833/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004834int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004835{
Willy Tarreau03209342016-12-22 17:08:28 +01004836 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004837 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004838 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004839 SSL_OP_ALL | /* all known workarounds for bugs */
4840 SSL_OP_NO_SSLv2 |
4841 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004842 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004843 SSL_MODE_ENABLE_PARTIAL_WRITE |
4844 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004845 SSL_MODE_RELEASE_BUFFERS |
4846 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004847 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004848 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004849 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004850 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004851 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004852
Thierry Fournier383085f2013-01-24 14:15:43 +01004853 /* Make sure openssl opens /dev/urandom before the chroot */
4854 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004855 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004856 cfgerr++;
4857 }
4858
Willy Tarreaufce03112015-01-15 21:32:40 +01004859 /* Automatic memory computations need to know we use SSL there */
4860 global.ssl_used_backend = 1;
4861
4862 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004863 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004864 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004865 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4866 curproxy->id, srv->id,
4867 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004868 cfgerr++;
4869 return cfgerr;
4870 }
4871 }
Emeric Brun94324a42012-10-11 14:00:19 +02004872 if (srv->use_ssl)
4873 srv->xprt = &ssl_sock;
4874 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004875 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004876
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004877 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004878 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004879 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4880 proxy_type_str(curproxy), curproxy->id,
4881 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004882 cfgerr++;
4883 return cfgerr;
4884 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004885
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004886 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004887 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4888 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4889 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004890 else
4891 flags = conf_ssl_methods->flags;
4892
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004893 /* Real min and max should be determinate with configuration and openssl's capabilities */
4894 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004895 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004896 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004897 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004898
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004899 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004900 min = max = CONF_TLSV_NONE;
4901 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004902 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004903 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004904 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004905 if (min) {
4906 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004907 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4908 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4909 proxy_type_str(curproxy), curproxy->id, srv->id,
4910 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004911 hole = 0;
4912 }
4913 max = i;
4914 }
4915 else {
4916 min = max = i;
4917 }
4918 }
4919 else {
4920 if (min)
4921 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004922 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004923 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004924 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4925 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004926 cfgerr += 1;
4927 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004928
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004929#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004930 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004931 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004932 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004933 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004934 else
4935 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4936 if (flags & methodVersions[i].flag)
4937 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004938#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004939 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004940 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4941 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004942#endif
4943
4944 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4945 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004946 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004947
Willy Tarreau5db847a2019-05-09 14:13:35 +02004948#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004949 if (global_ssl.async)
4950 mode |= SSL_MODE_ASYNC;
4951#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004952 SSL_CTX_set_mode(ctx, mode);
4953 srv->ssl_ctx.ctx = ctx;
4954
Emeric Bruna7aa3092012-10-26 12:58:00 +02004955 if (srv->ssl_ctx.client_crt) {
4956 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 +01004957 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4958 proxy_type_str(curproxy), curproxy->id,
4959 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004960 cfgerr++;
4961 }
4962 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 +01004963 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4964 proxy_type_str(curproxy), curproxy->id,
4965 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004966 cfgerr++;
4967 }
4968 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004969 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4970 proxy_type_str(curproxy), curproxy->id,
4971 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004972 cfgerr++;
4973 }
4974 }
Emeric Brun94324a42012-10-11 14:00:19 +02004975
Emeric Brun850efd52014-01-29 12:24:34 +01004976 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4977 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004978 switch (srv->ssl_ctx.verify) {
4979 case SSL_SOCK_VERIFY_NONE:
4980 verify = SSL_VERIFY_NONE;
4981 break;
4982 case SSL_SOCK_VERIFY_REQUIRED:
4983 verify = SSL_VERIFY_PEER;
4984 break;
4985 }
Evan Broderbe554312013-06-27 00:05:25 -07004986 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004987 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004988 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004989 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004990 if (srv->ssl_ctx.ca_file) {
4991 /* load CAfile to verify */
4992 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004993 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4994 curproxy->id, srv->id,
4995 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004996 cfgerr++;
4997 }
4998 }
Emeric Brun850efd52014-01-29 12:24:34 +01004999 else {
5000 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01005001 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",
5002 curproxy->id, srv->id,
5003 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005004 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01005005 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
5006 curproxy->id, srv->id,
5007 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01005008 cfgerr++;
5009 }
Emeric Brunef42d922012-10-11 16:11:36 +02005010#ifdef X509_V_FLAG_CRL_CHECK
5011 if (srv->ssl_ctx.crl_file) {
5012 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
5013
5014 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005015 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
5016 curproxy->id, srv->id,
5017 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02005018 cfgerr++;
5019 }
5020 else {
5021 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
5022 }
5023 }
5024#endif
5025 }
5026
Olivier Houchardbd84ac82017-11-03 13:43:35 +01005027 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
5028 SSL_SESS_CACHE_NO_INTERNAL_STORE);
5029 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02005030 if (srv->ssl_ctx.ciphers &&
5031 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005032 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5033 curproxy->id, srv->id,
5034 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005035 cfgerr++;
5036 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005037
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005038#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005039 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005040 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005041 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5042 curproxy->id, srv->id,
5043 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5044 cfgerr++;
5045 }
5046#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005047#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5048 if (srv->ssl_ctx.npn_str)
5049 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5050#endif
5051#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5052 if (srv->ssl_ctx.alpn_str)
5053 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5054#endif
5055
Emeric Brun94324a42012-10-11 14:00:19 +02005056
5057 return cfgerr;
5058}
5059
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005060/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005061 * be NULL, in which case nothing is done. Returns the number of errors
5062 * encountered.
5063 */
Willy Tarreau03209342016-12-22 17:08:28 +01005064int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005065{
5066 struct ebmb_node *node;
5067 struct sni_ctx *sni;
5068 int err = 0;
5069
Willy Tarreaufce03112015-01-15 21:32:40 +01005070 /* Automatic memory computations need to know we use SSL there */
5071 global.ssl_used_frontend = 1;
5072
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005073 /* Make sure openssl opens /dev/urandom before the chroot */
5074 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005075 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005076 err++;
5077 }
5078 /* Create initial_ctx used to start the ssl connection before do switchctx */
5079 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005080 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005081 /* It should not be necessary to call this function, but it's
5082 necessary first to check and move all initialisation related
5083 to initial_ctx in ssl_sock_initial_ctx. */
5084 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5085 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005086 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005087 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005088
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005089 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005090 while (node) {
5091 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005092 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5093 /* only initialize the CTX on its first occurrence and
5094 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005095 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005096 node = ebmb_next(node);
5097 }
5098
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005099 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005100 while (node) {
5101 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005102 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5103 /* only initialize the CTX on its first occurrence and
5104 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005105 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005106 node = ebmb_next(node);
5107 }
5108 return err;
5109}
5110
Willy Tarreau55d37912016-12-21 23:38:39 +01005111/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5112 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5113 * alerts are directly emitted since the rest of the stack does it below.
5114 */
5115int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5116{
5117 struct proxy *px = bind_conf->frontend;
5118 int alloc_ctx;
5119 int err;
5120
5121 if (!bind_conf->is_ssl) {
5122 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005123 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5124 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005125 }
5126 return 0;
5127 }
5128 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005129 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005130 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5131 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005132 }
5133 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005134 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5135 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005136 return -1;
5137 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005138 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005139 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005140 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005141 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005142 sizeof(*sh_ssl_sess_tree),
5143 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005144 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005145 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5146 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");
5147 else
5148 ha_alert("Unable to allocate SSL session cache.\n");
5149 return -1;
5150 }
5151 /* free block callback */
5152 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5153 /* init the root tree within the extra space */
5154 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5155 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005156 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005157 err = 0;
5158 /* initialize all certificate contexts */
5159 err += ssl_sock_prepare_all_ctx(bind_conf);
5160
5161 /* initialize CA variables if the certificates generation is enabled */
5162 err += ssl_sock_load_ca(bind_conf);
5163
5164 return -err;
5165}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005166
5167/* release ssl context allocated for servers. */
5168void ssl_sock_free_srv_ctx(struct server *srv)
5169{
Olivier Houchardc7566002018-11-20 23:33:50 +01005170#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5171 if (srv->ssl_ctx.alpn_str)
5172 free(srv->ssl_ctx.alpn_str);
5173#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005174#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005175 if (srv->ssl_ctx.npn_str)
5176 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005177#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005178 if (srv->ssl_ctx.ctx)
5179 SSL_CTX_free(srv->ssl_ctx.ctx);
5180}
5181
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005182/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005183 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5184 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005185void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005186{
5187 struct ebmb_node *node, *back;
5188 struct sni_ctx *sni;
5189
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005190 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005191 while (node) {
5192 sni = ebmb_entry(node, struct sni_ctx, name);
5193 back = ebmb_next(node);
5194 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005195 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005196 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005197 ssl_sock_free_ssl_conf(sni->conf);
5198 free(sni->conf);
5199 sni->conf = NULL;
5200 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005201 free(sni);
5202 node = back;
5203 }
5204
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005205 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005206 while (node) {
5207 sni = ebmb_entry(node, struct sni_ctx, name);
5208 back = ebmb_next(node);
5209 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005210 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005211 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005212 ssl_sock_free_ssl_conf(sni->conf);
5213 free(sni->conf);
5214 sni->conf = NULL;
5215 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005216 free(sni);
5217 node = back;
5218 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005219 SSL_CTX_free(bind_conf->initial_ctx);
5220 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005221 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005222 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005223}
5224
Willy Tarreau795cdab2016-12-22 17:30:54 +01005225/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5226void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5227{
5228 ssl_sock_free_ca(bind_conf);
5229 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005230 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005231 free(bind_conf->ca_sign_file);
5232 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005233 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005234 free(bind_conf->keys_ref->filename);
5235 free(bind_conf->keys_ref->tlskeys);
5236 LIST_DEL(&bind_conf->keys_ref->list);
5237 free(bind_conf->keys_ref);
5238 }
5239 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005240 bind_conf->ca_sign_pass = NULL;
5241 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005242}
5243
Christopher Faulet31af49d2015-06-09 17:29:50 +02005244/* Load CA cert file and private key used to generate certificates */
5245int
Willy Tarreau03209342016-12-22 17:08:28 +01005246ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005247{
Willy Tarreau03209342016-12-22 17:08:28 +01005248 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005249 FILE *fp;
5250 X509 *cacert = NULL;
5251 EVP_PKEY *capkey = NULL;
5252 int err = 0;
5253
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005254 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005255 return err;
5256
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005257#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005258 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005259 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005260 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005261 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005262 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005263#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005264
Christopher Faulet31af49d2015-06-09 17:29:50 +02005265 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005266 ha_alert("Proxy '%s': cannot enable certificate generation, "
5267 "no CA certificate File configured at [%s:%d].\n",
5268 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005269 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005270 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005271
5272 /* read in the CA certificate */
5273 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005274 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5275 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005276 goto load_error;
5277 }
5278 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005279 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5280 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005281 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005282 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005283 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005284 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005285 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5286 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005287 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005288 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005289
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005290 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005291 bind_conf->ca_sign_cert = cacert;
5292 bind_conf->ca_sign_pkey = capkey;
5293 return err;
5294
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005295 read_error:
5296 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005297 if (capkey) EVP_PKEY_free(capkey);
5298 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005299 load_error:
5300 bind_conf->generate_certs = 0;
5301 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005302 return err;
5303}
5304
5305/* Release CA cert and private key used to generate certificated */
5306void
5307ssl_sock_free_ca(struct bind_conf *bind_conf)
5308{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005309 if (bind_conf->ca_sign_pkey)
5310 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5311 if (bind_conf->ca_sign_cert)
5312 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005313 bind_conf->ca_sign_pkey = NULL;
5314 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005315}
5316
Emeric Brun46591952012-05-18 15:47:34 +02005317/*
5318 * This function is called if SSL * context is not yet allocated. The function
5319 * is designed to be called before any other data-layer operation and sets the
5320 * handshake flag on the connection. It is safe to call it multiple times.
5321 * It returns 0 on success and -1 in error case.
5322 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005323static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005324{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005325 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005326 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005327 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005328 return 0;
5329
Willy Tarreau3c728722014-01-23 13:50:42 +01005330 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005331 return 0;
5332
Olivier Houchard66ab4982019-02-26 18:37:15 +01005333 ctx = pool_alloc(ssl_sock_ctx_pool);
5334 if (!ctx) {
5335 conn->err_code = CO_ER_SSL_NO_MEM;
5336 return -1;
5337 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005338 ctx->wait_event.tasklet = tasklet_new();
5339 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005340 conn->err_code = CO_ER_SSL_NO_MEM;
5341 pool_free(ssl_sock_ctx_pool, ctx);
5342 return -1;
5343 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005344 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5345 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005346 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005347 ctx->sent_early_data = 0;
5348 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005349 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005350 ctx->send_wait = NULL;
5351 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005352 ctx->xprt_st = 0;
5353 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005354
5355 /* Only work with sockets for now, this should be adapted when we'll
5356 * add QUIC support.
5357 */
5358 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005359 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005360 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5361 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005362 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005363
Willy Tarreau20879a02012-12-03 16:32:10 +01005364 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5365 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005366 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005367 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005368
Emeric Brun46591952012-05-18 15:47:34 +02005369 /* If it is in client mode initiate SSL session
5370 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005371 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005372 int may_retry = 1;
5373
5374 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005375 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005376 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5377 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005378 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005379 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005380 goto retry_connect;
5381 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005382 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005383 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005384 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005385 ctx->bio = BIO_new(ha_meth);
5386 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005387 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005388 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005389 goto retry_connect;
5390 }
Emeric Brun55476152014-11-12 17:35:37 +01005391 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005392 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005393 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005394 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005395 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005396
Evan Broderbe554312013-06-27 00:05:25 -07005397 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005398 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5399 SSL_free(ctx->ssl);
5400 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005401 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005402 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005403 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005404 goto retry_connect;
5405 }
Emeric Brun55476152014-11-12 17:35:37 +01005406 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005407 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005408 }
5409
Olivier Houchard66ab4982019-02-26 18:37:15 +01005410 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005411 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5412 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5413 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 +01005414 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005415 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005416 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5417 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005418 } else if (sess) {
5419 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005420 }
5421 }
Evan Broderbe554312013-06-27 00:05:25 -07005422
Emeric Brun46591952012-05-18 15:47:34 +02005423 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005424 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005425
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005426 _HA_ATOMIC_ADD(&sslconns, 1);
5427 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005428 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005429 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005430 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005431 if (conn->flags & CO_FL_ERROR)
5432 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005433 return 0;
5434 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005435 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005436 int may_retry = 1;
5437
5438 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005439 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005440 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5441 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005442 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005443 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005444 goto retry_accept;
5445 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005446 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005447 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005448 }
Emeric Brun46591952012-05-18 15:47:34 +02005449
Olivier Houcharda8955d52019-04-07 22:00:38 +02005450 ctx->bio = BIO_new(ha_meth);
5451 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005452 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005453 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005454 goto retry_accept;
5455 }
Emeric Brun55476152014-11-12 17:35:37 +01005456 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005457 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005458 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005459 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005460 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005461
Emeric Brune1f38db2012-09-03 20:36:47 +02005462 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005463 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5464 SSL_free(ctx->ssl);
5465 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005466 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005467 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005468 goto retry_accept;
5469 }
Emeric Brun55476152014-11-12 17:35:37 +01005470 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005471 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005472 }
5473
Olivier Houchard66ab4982019-02-26 18:37:15 +01005474 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005475
Emeric Brun46591952012-05-18 15:47:34 +02005476 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005477 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005478#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005479 conn->flags |= CO_FL_EARLY_SSL_HS;
5480#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005481
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005482 _HA_ATOMIC_ADD(&sslconns, 1);
5483 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005484 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005485 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005486 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005487 if (conn->flags & CO_FL_ERROR)
5488 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005489 return 0;
5490 }
5491 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005492 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005493err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005494 if (ctx && ctx->wait_event.tasklet)
5495 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005496 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005497 return -1;
5498}
5499
5500
5501/* This is the callback which is used when an SSL handshake is pending. It
5502 * updates the FD status if it wants some polling before being called again.
5503 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5504 * otherwise it returns non-zero and removes itself from the connection's
5505 * flags (the bit is provided in <flag> by the caller).
5506 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005507static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005508{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005509 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005510 int ret;
5511
Willy Tarreau3c728722014-01-23 13:50:42 +01005512 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005513 return 0;
5514
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005515 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005516 goto out_error;
5517
Willy Tarreau5db847a2019-05-09 14:13:35 +02005518#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005519 /*
5520 * Check if we have early data. If we do, we have to read them
5521 * before SSL_do_handshake() is called, And there's no way to
5522 * detect early data, except to try to read them
5523 */
5524 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5525 size_t read_data;
5526
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005527 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005528 1, &read_data);
5529 if (ret == SSL_READ_EARLY_DATA_ERROR)
5530 goto check_error;
5531 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5532 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5533 return 1;
5534 } else
5535 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5536 }
5537#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005538 /* If we use SSL_do_handshake to process a reneg initiated by
5539 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5540 * Usually SSL_write and SSL_read are used and process implicitly
5541 * the reneg handshake.
5542 * Here we use SSL_peek as a workaround for reneg.
5543 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005544 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005545 char c;
5546
Olivier Houchard66ab4982019-02-26 18:37:15 +01005547 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005548 if (ret <= 0) {
5549 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005550 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005551
Emeric Brun674b7432012-11-08 19:21:55 +01005552 if (ret == SSL_ERROR_WANT_WRITE) {
5553 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005554 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005555 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005556 return 0;
5557 }
5558 else if (ret == SSL_ERROR_WANT_READ) {
5559 /* handshake may have been completed but we have
5560 * no more data to read.
5561 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005562 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005563 ret = 1;
5564 goto reneg_ok;
5565 }
5566 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005567 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005568 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005569 return 0;
5570 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005571#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005572 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005573 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005574 return 0;
5575 }
5576#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005577 else if (ret == SSL_ERROR_SYSCALL) {
5578 /* if errno is null, then connection was successfully established */
5579 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5580 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005581 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005582#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5583 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005584 conn->err_code = CO_ER_SSL_HANDSHAKE;
5585#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005586 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005587#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005588 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005589 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005590 empty_handshake = state == TLS_ST_BEFORE;
5591#else
Lukas Tribus49799162019-07-08 14:29:15 +02005592 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5593 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005594#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005595 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005596 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005597 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005598 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5599 else
5600 conn->err_code = CO_ER_SSL_EMPTY;
5601 }
5602 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005603 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005604 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5605 else
5606 conn->err_code = CO_ER_SSL_ABORT;
5607 }
5608 }
5609 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005610 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005611 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005612 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005613 conn->err_code = CO_ER_SSL_HANDSHAKE;
5614 }
Lukas Tribus49799162019-07-08 14:29:15 +02005615#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005616 }
Emeric Brun674b7432012-11-08 19:21:55 +01005617 goto out_error;
5618 }
5619 else {
5620 /* Fail on all other handshake errors */
5621 /* Note: OpenSSL may leave unread bytes in the socket's
5622 * buffer, causing an RST to be emitted upon close() on
5623 * TCP sockets. We first try to drain possibly pending
5624 * data to avoid this as much as possible.
5625 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005626 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005627 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005628 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005629 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005630 goto out_error;
5631 }
5632 }
5633 /* read some data: consider handshake completed */
5634 goto reneg_ok;
5635 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005636 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005637check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005638 if (ret != 1) {
5639 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005640 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005641
5642 if (ret == SSL_ERROR_WANT_WRITE) {
5643 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005644 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005645 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005646 return 0;
5647 }
5648 else if (ret == SSL_ERROR_WANT_READ) {
5649 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005650 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005651 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5652 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005653 return 0;
5654 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005655#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005656 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005657 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005658 return 0;
5659 }
5660#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005661 else if (ret == SSL_ERROR_SYSCALL) {
5662 /* if errno is null, then connection was successfully established */
5663 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5664 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005665 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005666#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5667 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005668 conn->err_code = CO_ER_SSL_HANDSHAKE;
5669#else
5670 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005671#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005672 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005673 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005674 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005675#else
Lukas Tribus49799162019-07-08 14:29:15 +02005676 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5677 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005678#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005679 if (empty_handshake) {
5680 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005681 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005682 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5683 else
5684 conn->err_code = CO_ER_SSL_EMPTY;
5685 }
5686 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005687 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005688 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5689 else
5690 conn->err_code = CO_ER_SSL_ABORT;
5691 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005692 }
5693 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005694 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005695 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5696 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005697 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005698 }
Lukas Tribus49799162019-07-08 14:29:15 +02005699#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005700 }
Willy Tarreau89230192012-09-28 20:22:13 +02005701 goto out_error;
5702 }
Emeric Brun46591952012-05-18 15:47:34 +02005703 else {
5704 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005705 /* Note: OpenSSL may leave unread bytes in the socket's
5706 * buffer, causing an RST to be emitted upon close() on
5707 * TCP sockets. We first try to drain possibly pending
5708 * data to avoid this as much as possible.
5709 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005710 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005711 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005712 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005713 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005714 goto out_error;
5715 }
5716 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005717#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005718 else {
5719 /*
5720 * If the server refused the early data, we have to send a
5721 * 425 to the client, as we no longer have the data to sent
5722 * them again.
5723 */
5724 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005725 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005726 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5727 goto out_error;
5728 }
5729 }
5730 }
5731#endif
5732
Emeric Brun46591952012-05-18 15:47:34 +02005733
Emeric Brun674b7432012-11-08 19:21:55 +01005734reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005735
Willy Tarreau5db847a2019-05-09 14:13:35 +02005736#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005737 /* ASYNC engine API doesn't support moving read/write
5738 * buffers. So we disable ASYNC mode right after
5739 * the handshake to avoid buffer oveflows.
5740 */
5741 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005742 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005743#endif
Emeric Brun46591952012-05-18 15:47:34 +02005744 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005745 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005746 if (objt_server(conn->target)) {
5747 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5748 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5749 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005750 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005751 else {
5752 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5753 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5754 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5755 }
Emeric Brun46591952012-05-18 15:47:34 +02005756 }
5757
5758 /* The connection is now established at both layers, it's time to leave */
5759 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5760 return 1;
5761
5762 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005763 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005764 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005765 ERR_clear_error();
5766
Emeric Brun9fa89732012-10-04 17:09:56 +02005767 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005768 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5769 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5770 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005771 }
5772
Emeric Brun46591952012-05-18 15:47:34 +02005773 /* Fail on all other handshake errors */
5774 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005775 if (!conn->err_code)
5776 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005777 return 0;
5778}
5779
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005780static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005781{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005782 struct wait_event *sw;
5783 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005784
Olivier Houchard0ff28652019-06-24 18:57:39 +02005785 if (!ctx)
5786 return -1;
5787
Olivier Houchardea8dd942019-05-20 14:02:16 +02005788 if (event_type & SUB_RETRY_RECV) {
5789 sw = param;
5790 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5791 sw->events |= SUB_RETRY_RECV;
5792 ctx->recv_wait = sw;
5793 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5794 !(ctx->wait_event.events & SUB_RETRY_RECV))
5795 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5796 event_type &= ~SUB_RETRY_RECV;
5797 }
5798 if (event_type & SUB_RETRY_SEND) {
5799sw = param;
5800 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5801 sw->events |= SUB_RETRY_SEND;
5802 ctx->send_wait = sw;
5803 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5804 !(ctx->wait_event.events & SUB_RETRY_SEND))
5805 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5806 event_type &= ~SUB_RETRY_SEND;
5807
5808 }
5809 if (event_type != 0)
5810 return -1;
5811 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005812}
5813
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005814static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005815{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005816 struct wait_event *sw;
5817 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005818
Olivier Houchardea8dd942019-05-20 14:02:16 +02005819 if (event_type & SUB_RETRY_RECV) {
5820 sw = param;
5821 BUG_ON(ctx->recv_wait != sw);
5822 ctx->recv_wait = NULL;
5823 sw->events &= ~SUB_RETRY_RECV;
5824 /* If we subscribed, and we're not doing the handshake,
5825 * then we subscribed because the upper layer asked for it,
5826 * as the upper layer is no longer interested, we can
5827 * unsubscribe too.
5828 */
5829 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5830 (ctx->wait_event.events & SUB_RETRY_RECV))
5831 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5832 &ctx->wait_event);
5833 }
5834 if (event_type & SUB_RETRY_SEND) {
5835 sw = param;
5836 BUG_ON(ctx->send_wait != sw);
5837 ctx->send_wait = NULL;
5838 sw->events &= ~SUB_RETRY_SEND;
5839 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5840 (ctx->wait_event.events & SUB_RETRY_SEND))
5841 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5842 &ctx->wait_event);
5843
5844 }
5845
5846 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005847}
5848
Olivier Houchard2e055482019-05-27 19:50:12 +02005849/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5850 * Returns 0 on success, and non-zero on failure.
5851 */
5852static int ssl_add_xprt(struct connection *conn, void *xprt_ctx, void *toadd_ctx, const struct xprt_ops *toadd_ops, void **oldxprt_ctx, const struct xprt_ops **oldxprt_ops)
5853{
5854 struct ssl_sock_ctx *ctx = xprt_ctx;
5855
5856 if (oldxprt_ops != NULL)
5857 *oldxprt_ops = ctx->xprt;
5858 if (oldxprt_ctx != NULL)
5859 *oldxprt_ctx = ctx->xprt_ctx;
5860 ctx->xprt = toadd_ops;
5861 ctx->xprt_ctx = toadd_ctx;
5862 return 0;
5863}
5864
Olivier Houchard5149b592019-05-23 17:47:36 +02005865/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5866 * return 0, otherwise just call the remove_xprt method from the underlying
5867 * XPRT.
5868 */
5869static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5870{
5871 struct ssl_sock_ctx *ctx = xprt_ctx;
5872
5873 if (ctx->xprt_ctx == toremove_ctx) {
5874 ctx->xprt_ctx = newctx;
5875 ctx->xprt = newops;
5876 return 0;
5877 }
5878 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5879}
5880
Olivier Houchardea8dd942019-05-20 14:02:16 +02005881static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5882{
5883 struct ssl_sock_ctx *ctx = context;
5884
5885 /* First if we're doing an handshake, try that */
5886 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5887 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5888 /* If we had an error, or the handshake is done and I/O is available,
5889 * let the upper layer know.
5890 * If no mux was set up yet, and nobody subscribed, then call
5891 * xprt_done_cb() ourself if it's set, or destroy the connection,
5892 * we can't be sure conn_fd_handler() will be called again.
5893 */
5894 if ((ctx->conn->flags & CO_FL_ERROR) ||
5895 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5896 int ret = 0;
5897 int woke = 0;
5898
5899 /* On error, wake any waiter */
5900 if (ctx->recv_wait) {
5901 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005902 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005903 ctx->recv_wait = NULL;
5904 woke = 1;
5905 }
5906 if (ctx->send_wait) {
5907 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005908 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005909 ctx->send_wait = NULL;
5910 woke = 1;
5911 }
5912 /* If we're the first xprt for the connection, let the
5913 * upper layers know. If xprt_done_cb() is set, call it,
5914 * otherwise, we should have a mux, so call its wake
5915 * method if we didn't woke a tasklet already.
5916 */
5917 if (ctx->conn->xprt_ctx == ctx) {
5918 if (ctx->conn->xprt_done_cb)
5919 ret = ctx->conn->xprt_done_cb(ctx->conn);
5920 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5921 ctx->conn->mux->wake(ctx->conn);
5922 return NULL;
5923 }
5924 }
5925 return NULL;
5926}
5927
Emeric Brun46591952012-05-18 15:47:34 +02005928/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005929 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005930 * buffer wraps, in which case a second call may be performed. The connection's
5931 * flags are updated with whatever special event is detected (error, read0,
5932 * empty). The caller is responsible for taking care of those events and
5933 * avoiding the call if inappropriate. The function does not call the
5934 * connection's polling update function, so the caller is responsible for this.
5935 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005936static 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 +02005937{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005938 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005939 ssize_t ret;
5940 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005941
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005942 conn_refresh_polling_flags(conn);
5943
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005944 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005945 goto out_error;
5946
5947 if (conn->flags & CO_FL_HANDSHAKE)
5948 /* a handshake was requested */
5949 return 0;
5950
Emeric Brun46591952012-05-18 15:47:34 +02005951 /* read the largest possible block. For this, we perform only one call
5952 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5953 * in which case we accept to do it once again. A new attempt is made on
5954 * EINTR too.
5955 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005956 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005957 int need_out = 0;
5958
Willy Tarreau591d4452018-06-15 17:21:00 +02005959 try = b_contig_space(buf);
5960 if (!try)
5961 break;
5962
Willy Tarreauabf08d92014-01-14 11:31:27 +01005963 if (try > count)
5964 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005965
Olivier Houchardc2aae742017-09-22 18:26:28 +02005966 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005967 ctx->tmp_early_data != -1) {
5968 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005969 done++;
5970 try--;
5971 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005972 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005973 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005974 continue;
5975 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005976
Willy Tarreau5db847a2019-05-09 14:13:35 +02005977#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005978 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5979 size_t read_length;
5980
Olivier Houchard66ab4982019-02-26 18:37:15 +01005981 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005982 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005983 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5984 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005985 conn->flags |= CO_FL_EARLY_DATA;
5986 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5987 ret == SSL_READ_EARLY_DATA_FINISH) {
5988 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5989 /*
5990 * We're done reading the early data,
5991 * let's make the handshake
5992 */
5993 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5994 conn->flags |= CO_FL_SSL_WAIT_HS;
5995 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005996 /* Now initiate the handshake */
5997 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005998 if (read_length == 0)
5999 break;
6000 }
6001 ret = read_length;
6002 }
6003 } else
6004#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006005 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02006006
Emeric Brune1f38db2012-09-03 20:36:47 +02006007 if (conn->flags & CO_FL_ERROR) {
6008 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006009 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006010 }
Emeric Brun46591952012-05-18 15:47:34 +02006011 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02006012 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006013 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006014 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006015 }
Emeric Brun46591952012-05-18 15:47:34 +02006016 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006017 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02006018 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006019 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02006020 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006021 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006022#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006023 /* Async mode can be re-enabled, because we're leaving data state.*/
6024 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006025 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006026#endif
Emeric Brun46591952012-05-18 15:47:34 +02006027 break;
6028 }
6029 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006030 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006031 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6032 SUB_RETRY_RECV,
6033 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006034 /* handshake is running, and it may need to re-enable read */
6035 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006036#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006037 /* Async mode can be re-enabled, because we're leaving data state.*/
6038 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006039 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006040#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006041 break;
6042 }
Emeric Brun46591952012-05-18 15:47:34 +02006043 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006044 } else if (ret == SSL_ERROR_ZERO_RETURN)
6045 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006046 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6047 * stack before shutting down the connection for
6048 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006049 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6050 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006051 /* otherwise it's a real error */
6052 goto out_error;
6053 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006054 if (need_out)
6055 break;
Emeric Brun46591952012-05-18 15:47:34 +02006056 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006057 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006058 return done;
6059
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006060 clear_ssl_error:
6061 /* Clear openssl global errors stack */
6062 ssl_sock_dump_errors(conn);
6063 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006064 read0:
6065 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006066 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006067
Emeric Brun46591952012-05-18 15:47:34 +02006068 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006069 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006070 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006071 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006072 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006073 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006074}
6075
6076
Willy Tarreau787db9a2018-06-14 18:31:46 +02006077/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6078 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6079 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006080 * Only one call to send() is performed, unless the buffer wraps, in which case
6081 * a second call may be performed. The connection's flags are updated with
6082 * whatever special event is detected (error, empty). The caller is responsible
6083 * for taking care of those events and avoiding the call if inappropriate. The
6084 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006085 * is responsible for this. The buffer's output is not adjusted, it's up to the
6086 * caller to take care of this. It's up to the caller to update the buffer's
6087 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006088 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006089static 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 +02006090{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006091 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006092 ssize_t ret;
6093 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006094
6095 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006096 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006097
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006098 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006099 goto out_error;
6100
Olivier Houchard010941f2019-05-03 20:56:19 +02006101 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006102 /* a handshake was requested */
6103 return 0;
6104
6105 /* send the largest possible block. For this we perform only one call
6106 * to send() unless the buffer wraps and we exactly fill the first hunk,
6107 * in which case we accept to do it once again.
6108 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006109 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006110#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006111 size_t written_data;
6112#endif
6113
Willy Tarreau787db9a2018-06-14 18:31:46 +02006114 try = b_contig_data(buf, done);
6115 if (try > count)
6116 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006117
Willy Tarreau7bed9452014-02-02 02:00:24 +01006118 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006119 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006120 global_ssl.max_record && try > global_ssl.max_record) {
6121 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006122 }
6123 else {
6124 /* we need to keep the information about the fact that
6125 * we're not limiting the upcoming send(), because if it
6126 * fails, we'll have to retry with at least as many data.
6127 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006128 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006129 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006130
Willy Tarreau5db847a2019-05-09 14:13:35 +02006131#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006132 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006133 unsigned int max_early;
6134
Olivier Houchard522eea72017-11-03 16:27:47 +01006135 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006136 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006137 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006138 if (SSL_get0_session(ctx->ssl))
6139 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006140 else
6141 max_early = 0;
6142 }
6143
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006144 if (try + ctx->sent_early_data > max_early) {
6145 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006146 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006147 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006148 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006149 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006150 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006151 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006152 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006153 if (ret == 1) {
6154 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006155 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006156 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006157 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006158 /* Initiate the handshake, now */
6159 tasklet_wakeup(ctx->wait_event.tasklet);
6160 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006161
Olivier Houchardc2aae742017-09-22 18:26:28 +02006162 }
6163
6164 } else
6165#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006166 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006167
Emeric Brune1f38db2012-09-03 20:36:47 +02006168 if (conn->flags & CO_FL_ERROR) {
6169 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006170 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006171 }
Emeric Brun46591952012-05-18 15:47:34 +02006172 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006173 /* A send succeeded, so we can consier ourself connected */
6174 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006175 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006176 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006177 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006178 }
6179 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006180 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006181
Emeric Brun46591952012-05-18 15:47:34 +02006182 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006183 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006184 /* handshake is running, and it may need to re-enable write */
6185 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006186 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006187#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006188 /* Async mode can be re-enabled, because we're leaving data state.*/
6189 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006190 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006191#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006192 break;
6193 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006194
Emeric Brun46591952012-05-18 15:47:34 +02006195 break;
6196 }
6197 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006198 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006199 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006200 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6201 SUB_RETRY_RECV,
6202 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006203#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006204 /* Async mode can be re-enabled, because we're leaving data state.*/
6205 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006206 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006207#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006208 break;
6209 }
Emeric Brun46591952012-05-18 15:47:34 +02006210 goto out_error;
6211 }
6212 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006213 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006214 return done;
6215
6216 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006217 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006218 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006219 ERR_clear_error();
6220
Emeric Brun46591952012-05-18 15:47:34 +02006221 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006222 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006223}
6224
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006225static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006226
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006227 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006228
Olivier Houchardea8dd942019-05-20 14:02:16 +02006229
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006230 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006231 if (ctx->wait_event.events != 0)
6232 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6233 ctx->wait_event.events,
6234 &ctx->wait_event);
6235 if (ctx->send_wait) {
6236 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006237 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006238 }
6239 if (ctx->recv_wait) {
6240 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006241 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006242 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006243 if (ctx->xprt->close)
6244 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006245#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006246 if (global_ssl.async) {
6247 OSSL_ASYNC_FD all_fd[32], afd;
6248 size_t num_all_fds = 0;
6249 int i;
6250
Olivier Houchard66ab4982019-02-26 18:37:15 +01006251 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006252 if (num_all_fds > 32) {
6253 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6254 return;
6255 }
6256
Olivier Houchard66ab4982019-02-26 18:37:15 +01006257 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006258
6259 /* If an async job is pending, we must try to
6260 to catch the end using polling before calling
6261 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006262 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006263 for (i=0 ; i < num_all_fds ; i++) {
6264 /* switch on an handler designed to
6265 * handle the SSL_free
6266 */
6267 afd = all_fd[i];
6268 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006269 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006270 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006271 /* To ensure that the fd cache won't be used
6272 * and we'll catch a real RD event.
6273 */
6274 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006275 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006276 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006277 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006278 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006279 return;
6280 }
Emeric Brun3854e012017-05-17 20:42:48 +02006281 /* Else we can remove the fds from the fdtab
6282 * and call SSL_free.
6283 * note: we do a fd_remove and not a delete
6284 * because the fd is owned by the engine.
6285 * the engine is responsible to close
6286 */
6287 for (i=0 ; i < num_all_fds ; i++)
6288 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006289 }
6290#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006291 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006292 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006293 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006294 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006295 }
Emeric Brun46591952012-05-18 15:47:34 +02006296}
6297
6298/* This function tries to perform a clean shutdown on an SSL connection, and in
6299 * any case, flags the connection as reusable if no handshake was in progress.
6300 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006301static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006302{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006303 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006304
Emeric Brun46591952012-05-18 15:47:34 +02006305 if (conn->flags & CO_FL_HANDSHAKE)
6306 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006307 if (!clean)
6308 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006309 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006310 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006311 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006312 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006313 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006314 ERR_clear_error();
6315 }
Emeric Brun46591952012-05-18 15:47:34 +02006316}
6317
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006318/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006319int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006320{
Christopher Faulet82004142019-09-10 10:12:03 +02006321 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006322 struct pkey_info *pkinfo;
6323 int bits = 0;
6324 int sig = TLSEXT_signature_anonymous;
6325 int len = -1;
6326
6327 if (!ssl_sock_is_ssl(conn))
6328 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006329 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006330 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006331 if (pkinfo) {
6332 sig = pkinfo->sig;
6333 bits = pkinfo->bits;
6334 } else {
6335 /* multicert and generated cert have no pkey info */
6336 X509 *crt;
6337 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006338 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006339 if (!crt)
6340 return 0;
6341 pkey = X509_get_pubkey(crt);
6342 if (pkey) {
6343 bits = EVP_PKEY_bits(pkey);
6344 switch(EVP_PKEY_base_id(pkey)) {
6345 case EVP_PKEY_RSA:
6346 sig = TLSEXT_signature_rsa;
6347 break;
6348 case EVP_PKEY_EC:
6349 sig = TLSEXT_signature_ecdsa;
6350 break;
6351 case EVP_PKEY_DSA:
6352 sig = TLSEXT_signature_dsa;
6353 break;
6354 }
6355 EVP_PKEY_free(pkey);
6356 }
6357 }
6358
6359 switch(sig) {
6360 case TLSEXT_signature_rsa:
6361 len = chunk_printf(out, "RSA%d", bits);
6362 break;
6363 case TLSEXT_signature_ecdsa:
6364 len = chunk_printf(out, "EC%d", bits);
6365 break;
6366 case TLSEXT_signature_dsa:
6367 len = chunk_printf(out, "DSA%d", bits);
6368 break;
6369 default:
6370 return 0;
6371 }
6372 if (len < 0)
6373 return 0;
6374 return 1;
6375}
6376
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006377/* used for ppv2 cert signature (can be used for logging) */
6378const char *ssl_sock_get_cert_sig(struct connection *conn)
6379{
Christopher Faulet82004142019-09-10 10:12:03 +02006380 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006381
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006382 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6383 X509 *crt;
6384
6385 if (!ssl_sock_is_ssl(conn))
6386 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006387 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006388 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006389 if (!crt)
6390 return NULL;
6391 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6392 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6393}
6394
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006395/* used for ppv2 authority */
6396const char *ssl_sock_get_sni(struct connection *conn)
6397{
6398#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006399 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006400
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006401 if (!ssl_sock_is_ssl(conn))
6402 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006403 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006404 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006405#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006406 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006407#endif
6408}
6409
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006410/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006411const char *ssl_sock_get_cipher_name(struct connection *conn)
6412{
Christopher Faulet82004142019-09-10 10:12:03 +02006413 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006414
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006415 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006416 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006417 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006418 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006419}
6420
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006421/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006422const char *ssl_sock_get_proto_version(struct connection *conn)
6423{
Christopher Faulet82004142019-09-10 10:12:03 +02006424 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006425
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006426 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006427 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006428 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006429 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006430}
6431
Willy Tarreau8d598402012-10-22 17:58:39 +02006432/* Extract a serial from a cert, and copy it to a chunk.
6433 * Returns 1 if serial is found and copied, 0 if no serial found and
6434 * -1 if output is not large enough.
6435 */
6436static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006437ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006438{
6439 ASN1_INTEGER *serial;
6440
6441 serial = X509_get_serialNumber(crt);
6442 if (!serial)
6443 return 0;
6444
6445 if (out->size < serial->length)
6446 return -1;
6447
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006448 memcpy(out->area, serial->data, serial->length);
6449 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006450 return 1;
6451}
6452
Emeric Brun43e79582014-10-29 19:03:26 +01006453/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006454 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6455 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006456 */
6457static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006458ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006459{
6460 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006461 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006462
6463 len =i2d_X509(crt, NULL);
6464 if (len <= 0)
6465 return 1;
6466
6467 if (out->size < len)
6468 return -1;
6469
6470 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006471 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006472 return 1;
6473}
6474
Emeric Brunce5ad802012-10-22 14:11:22 +02006475
Willy Tarreau83061a82018-07-13 11:56:34 +02006476/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006477 * Returns 1 if serial is found and copied, 0 if no valid time found
6478 * and -1 if output is not large enough.
6479 */
6480static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006481ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006482{
6483 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6484 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6485
6486 if (gentm->length < 12)
6487 return 0;
6488 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6489 return 0;
6490 if (out->size < gentm->length-2)
6491 return -1;
6492
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006493 memcpy(out->area, gentm->data+2, gentm->length-2);
6494 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006495 return 1;
6496 }
6497 else if (tm->type == V_ASN1_UTCTIME) {
6498 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6499
6500 if (utctm->length < 10)
6501 return 0;
6502 if (utctm->data[0] >= 0x35)
6503 return 0;
6504 if (out->size < utctm->length)
6505 return -1;
6506
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006507 memcpy(out->area, utctm->data, utctm->length);
6508 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006509 return 1;
6510 }
6511
6512 return 0;
6513}
6514
Emeric Brun87855892012-10-17 17:39:35 +02006515/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6516 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6517 */
6518static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006519ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6520 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006521{
6522 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006523 ASN1_OBJECT *obj;
6524 ASN1_STRING *data;
6525 const unsigned char *data_ptr;
6526 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006527 int i, j, n;
6528 int cur = 0;
6529 const char *s;
6530 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006531 int name_count;
6532
6533 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006534
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006535 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006536 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006537 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006538 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006539 else
6540 j = i;
6541
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006542 ne = X509_NAME_get_entry(a, j);
6543 obj = X509_NAME_ENTRY_get_object(ne);
6544 data = X509_NAME_ENTRY_get_data(ne);
6545 data_ptr = ASN1_STRING_get0_data(data);
6546 data_len = ASN1_STRING_length(data);
6547 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006548 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006549 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006550 s = tmp;
6551 }
6552
6553 if (chunk_strcasecmp(entry, s) != 0)
6554 continue;
6555
6556 if (pos < 0)
6557 cur--;
6558 else
6559 cur++;
6560
6561 if (cur != pos)
6562 continue;
6563
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006564 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006565 return -1;
6566
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006567 memcpy(out->area, data_ptr, data_len);
6568 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006569 return 1;
6570 }
6571
6572 return 0;
6573
6574}
6575
6576/* Extract and format full DN from a X509_NAME and copy result into a chunk
6577 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6578 */
6579static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006580ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006581{
6582 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006583 ASN1_OBJECT *obj;
6584 ASN1_STRING *data;
6585 const unsigned char *data_ptr;
6586 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006587 int i, n, ln;
6588 int l = 0;
6589 const char *s;
6590 char *p;
6591 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006592 int name_count;
6593
6594
6595 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006596
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006597 out->data = 0;
6598 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006599 for (i = 0; i < name_count; i++) {
6600 ne = X509_NAME_get_entry(a, i);
6601 obj = X509_NAME_ENTRY_get_object(ne);
6602 data = X509_NAME_ENTRY_get_data(ne);
6603 data_ptr = ASN1_STRING_get0_data(data);
6604 data_len = ASN1_STRING_length(data);
6605 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006606 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006607 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006608 s = tmp;
6609 }
6610 ln = strlen(s);
6611
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006612 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006613 if (l > out->size)
6614 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006615 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006616
6617 *(p++)='/';
6618 memcpy(p, s, ln);
6619 p += ln;
6620 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006621 memcpy(p, data_ptr, data_len);
6622 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006623 }
6624
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006625 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006626 return 0;
6627
6628 return 1;
6629}
6630
Olivier Houchardab28a322018-12-21 19:45:40 +01006631void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6632{
6633#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02006634 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006635
Olivier Houcharde488ea82019-06-28 14:10:33 +02006636 if (!ssl_sock_is_ssl(conn))
6637 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006638 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006639 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006640#endif
6641}
6642
Willy Tarreau119a4082016-12-22 21:58:38 +01006643/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6644 * to disable SNI.
6645 */
Willy Tarreau63076412015-07-10 11:33:32 +02006646void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6647{
6648#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006649 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006650
Willy Tarreau119a4082016-12-22 21:58:38 +01006651 char *prev_name;
6652
Willy Tarreau63076412015-07-10 11:33:32 +02006653 if (!ssl_sock_is_ssl(conn))
6654 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006655 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006656
Willy Tarreau119a4082016-12-22 21:58:38 +01006657 /* if the SNI changes, we must destroy the reusable context so that a
6658 * new connection will present a new SNI. As an optimization we could
6659 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6660 * server.
6661 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006662 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006663 if ((!prev_name && hostname) ||
6664 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006665 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006666
Olivier Houchard66ab4982019-02-26 18:37:15 +01006667 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006668#endif
6669}
6670
Emeric Brun0abf8362014-06-24 18:26:41 +02006671/* Extract peer certificate's common name into the chunk dest
6672 * Returns
6673 * the len of the extracted common name
6674 * or 0 if no CN found in DN
6675 * or -1 on error case (i.e. no peer certificate)
6676 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006677int ssl_sock_get_remote_common_name(struct connection *conn,
6678 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006679{
Christopher Faulet82004142019-09-10 10:12:03 +02006680 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006681 X509 *crt = NULL;
6682 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006683 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006684 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006685 .area = (char *)&find_cn,
6686 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006687 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006688 int result = -1;
David Safb76832014-05-08 23:42:08 -04006689
6690 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006691 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02006692 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006693
6694 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006695 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006696 if (!crt)
6697 goto out;
6698
6699 name = X509_get_subject_name(crt);
6700 if (!name)
6701 goto out;
David Safb76832014-05-08 23:42:08 -04006702
Emeric Brun0abf8362014-06-24 18:26:41 +02006703 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6704out:
David Safb76832014-05-08 23:42:08 -04006705 if (crt)
6706 X509_free(crt);
6707
6708 return result;
6709}
6710
Dave McCowan328fb582014-07-30 10:39:13 -04006711/* returns 1 if client passed a certificate for this session, 0 if not */
6712int ssl_sock_get_cert_used_sess(struct connection *conn)
6713{
Christopher Faulet82004142019-09-10 10:12:03 +02006714 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006715 X509 *crt = NULL;
6716
6717 if (!ssl_sock_is_ssl(conn))
6718 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006719 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006720
6721 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006722 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006723 if (!crt)
6724 return 0;
6725
6726 X509_free(crt);
6727 return 1;
6728}
6729
6730/* returns 1 if client passed a certificate for this connection, 0 if not */
6731int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006732{
Christopher Faulet82004142019-09-10 10:12:03 +02006733 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006734
David Safb76832014-05-08 23:42:08 -04006735 if (!ssl_sock_is_ssl(conn))
6736 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006737 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006738 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006739}
6740
6741/* returns result from SSL verify */
6742unsigned int ssl_sock_get_verify_result(struct connection *conn)
6743{
Christopher Faulet82004142019-09-10 10:12:03 +02006744 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006745
David Safb76832014-05-08 23:42:08 -04006746 if (!ssl_sock_is_ssl(conn))
6747 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02006748 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006749 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006750}
6751
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006752/* Returns the application layer protocol name in <str> and <len> when known.
6753 * Zero is returned if the protocol name was not found, otherwise non-zero is
6754 * returned. The string is allocated in the SSL context and doesn't have to be
6755 * freed by the caller. NPN is also checked if available since older versions
6756 * of openssl (1.0.1) which are more common in field only support this one.
6757 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006758static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006759{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006760#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6761 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006762 struct ssl_sock_ctx *ctx = xprt_ctx;
6763 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006764 return 0;
6765
6766 *str = NULL;
6767
6768#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006769 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006770 if (*str)
6771 return 1;
6772#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006773#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006774 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006775 if (*str)
6776 return 1;
6777#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006778#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006779 return 0;
6780}
6781
Willy Tarreau7875d092012-09-10 08:20:03 +02006782/***** Below are some sample fetching functions for ACL/patterns *****/
6783
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006784static int
6785smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6786{
6787 struct connection *conn;
6788
6789 conn = objt_conn(smp->sess->origin);
6790 if (!conn || conn->xprt != &ssl_sock)
6791 return 0;
6792
6793 smp->flags = 0;
6794 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006795#ifdef OPENSSL_IS_BORINGSSL
6796 {
6797 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6798 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6799 SSL_early_data_accepted(ctx->ssl));
6800 }
6801#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006802 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6803 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006804#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006805 return 1;
6806}
6807
Emeric Brune64aef12012-09-21 13:15:06 +02006808/* boolean, returns true if client cert was present */
6809static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006810smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006811{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006812 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006813 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006814
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006815 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006816 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006817 return 0;
6818
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006819 ctx = conn->xprt_ctx;
6820
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006821 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006822 smp->flags |= SMP_F_MAY_CHANGE;
6823 return 0;
6824 }
6825
6826 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006827 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006828 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006829
6830 return 1;
6831}
6832
Emeric Brun43e79582014-10-29 19:03:26 +01006833/* binary, returns a certificate in a binary chunk (der/raw).
6834 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6835 * should be use.
6836 */
6837static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006838smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006839{
6840 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6841 X509 *crt = NULL;
6842 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006843 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006844 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006845 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006846
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006847 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006848 if (!conn || conn->xprt != &ssl_sock)
6849 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006850 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006851
6852 if (!(conn->flags & CO_FL_CONNECTED)) {
6853 smp->flags |= SMP_F_MAY_CHANGE;
6854 return 0;
6855 }
6856
6857 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006858 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006859 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006860 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006861
6862 if (!crt)
6863 goto out;
6864
6865 smp_trash = get_trash_chunk();
6866 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6867 goto out;
6868
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006869 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006870 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006871 ret = 1;
6872out:
6873 /* SSL_get_peer_certificate, it increase X509 * ref count */
6874 if (cert_peer && crt)
6875 X509_free(crt);
6876 return ret;
6877}
6878
Emeric Brunba841a12014-04-30 17:05:08 +02006879/* binary, returns serial of certificate in a binary chunk.
6880 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6881 * should be use.
6882 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006883static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006884smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006885{
Emeric Brunba841a12014-04-30 17:05:08 +02006886 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006887 X509 *crt = NULL;
6888 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006889 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006890 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006891 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006892
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006893 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006894 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006895 return 0;
6896
Olivier Houchard66ab4982019-02-26 18:37:15 +01006897 ctx = conn->xprt_ctx;
6898
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006899 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006900 smp->flags |= SMP_F_MAY_CHANGE;
6901 return 0;
6902 }
6903
Emeric Brunba841a12014-04-30 17:05:08 +02006904 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006905 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006906 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006907 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006908
Willy Tarreau8d598402012-10-22 17:58:39 +02006909 if (!crt)
6910 goto out;
6911
Willy Tarreau47ca5452012-12-23 20:22:19 +01006912 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006913 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6914 goto out;
6915
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006916 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006917 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006918 ret = 1;
6919out:
Emeric Brunba841a12014-04-30 17:05:08 +02006920 /* SSL_get_peer_certificate, it increase X509 * ref count */
6921 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006922 X509_free(crt);
6923 return ret;
6924}
Emeric Brune64aef12012-09-21 13:15:06 +02006925
Emeric Brunba841a12014-04-30 17:05:08 +02006926/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6927 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6928 * should be use.
6929 */
James Votha051b4a2013-05-14 20:37:59 +02006930static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006931smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006932{
Emeric Brunba841a12014-04-30 17:05:08 +02006933 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006934 X509 *crt = NULL;
6935 const EVP_MD *digest;
6936 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006937 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006938 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006939 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006940
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006941 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006942 if (!conn || conn->xprt != &ssl_sock)
6943 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006944 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006945
6946 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006947 smp->flags |= SMP_F_MAY_CHANGE;
6948 return 0;
6949 }
6950
Emeric Brunba841a12014-04-30 17:05:08 +02006951 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006952 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006953 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006954 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006955 if (!crt)
6956 goto out;
6957
6958 smp_trash = get_trash_chunk();
6959 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006960 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6961 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006962
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006963 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006964 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006965 ret = 1;
6966out:
Emeric Brunba841a12014-04-30 17:05:08 +02006967 /* SSL_get_peer_certificate, it increase X509 * ref count */
6968 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006969 X509_free(crt);
6970 return ret;
6971}
6972
Emeric Brunba841a12014-04-30 17:05:08 +02006973/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6974 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6975 * should be use.
6976 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006977static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006978smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006979{
Emeric Brunba841a12014-04-30 17:05:08 +02006980 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006981 X509 *crt = NULL;
6982 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006983 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006984 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006985 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006986
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006987 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006988 if (!conn || conn->xprt != &ssl_sock)
6989 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006990 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006991
6992 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006993 smp->flags |= SMP_F_MAY_CHANGE;
6994 return 0;
6995 }
6996
Emeric Brunba841a12014-04-30 17:05:08 +02006997 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006998 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006999 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007000 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007001 if (!crt)
7002 goto out;
7003
Willy Tarreau47ca5452012-12-23 20:22:19 +01007004 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007005 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007006 goto out;
7007
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007008 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007009 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007010 ret = 1;
7011out:
Emeric Brunba841a12014-04-30 17:05:08 +02007012 /* SSL_get_peer_certificate, it increase X509 * ref count */
7013 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007014 X509_free(crt);
7015 return ret;
7016}
7017
Emeric Brunba841a12014-04-30 17:05:08 +02007018/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
7019 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7020 * should be use.
7021 */
Emeric Brun87855892012-10-17 17:39:35 +02007022static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007023smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007024{
Emeric Brunba841a12014-04-30 17:05:08 +02007025 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007026 X509 *crt = NULL;
7027 X509_NAME *name;
7028 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007029 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007030 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007031 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007032
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007033 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007034 if (!conn || conn->xprt != &ssl_sock)
7035 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007036 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007037
7038 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007039 smp->flags |= SMP_F_MAY_CHANGE;
7040 return 0;
7041 }
7042
Emeric Brunba841a12014-04-30 17:05:08 +02007043 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007044 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007045 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007046 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007047 if (!crt)
7048 goto out;
7049
7050 name = X509_get_issuer_name(crt);
7051 if (!name)
7052 goto out;
7053
Willy Tarreau47ca5452012-12-23 20:22:19 +01007054 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007055 if (args && args[0].type == ARGT_STR) {
7056 int pos = 1;
7057
7058 if (args[1].type == ARGT_SINT)
7059 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007060
7061 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7062 goto out;
7063 }
7064 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7065 goto out;
7066
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007067 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007068 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007069 ret = 1;
7070out:
Emeric Brunba841a12014-04-30 17:05:08 +02007071 /* SSL_get_peer_certificate, it increase X509 * ref count */
7072 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007073 X509_free(crt);
7074 return ret;
7075}
7076
Emeric Brunba841a12014-04-30 17:05:08 +02007077/* string, returns notbefore date in ASN1_UTCTIME format.
7078 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7079 * should be use.
7080 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007081static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007082smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007083{
Emeric Brunba841a12014-04-30 17:05:08 +02007084 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007085 X509 *crt = NULL;
7086 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007087 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007088 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007089 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007090
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007091 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007092 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007093 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007094 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007095
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007096 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007097 smp->flags |= SMP_F_MAY_CHANGE;
7098 return 0;
7099 }
7100
Emeric Brunba841a12014-04-30 17:05:08 +02007101 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007102 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007103 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007104 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007105 if (!crt)
7106 goto out;
7107
Willy Tarreau47ca5452012-12-23 20:22:19 +01007108 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007109 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007110 goto out;
7111
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007112 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007113 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007114 ret = 1;
7115out:
Emeric Brunba841a12014-04-30 17:05:08 +02007116 /* SSL_get_peer_certificate, it increase X509 * ref count */
7117 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007118 X509_free(crt);
7119 return ret;
7120}
7121
Emeric Brunba841a12014-04-30 17:05:08 +02007122/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7123 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7124 * should be use.
7125 */
Emeric Brun87855892012-10-17 17:39:35 +02007126static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007127smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007128{
Emeric Brunba841a12014-04-30 17:05:08 +02007129 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007130 X509 *crt = NULL;
7131 X509_NAME *name;
7132 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007133 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007134 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007135 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007136
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007137 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007138 if (!conn || conn->xprt != &ssl_sock)
7139 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007140 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007141
7142 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007143 smp->flags |= SMP_F_MAY_CHANGE;
7144 return 0;
7145 }
7146
Emeric Brunba841a12014-04-30 17:05:08 +02007147 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007148 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007149 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007150 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007151 if (!crt)
7152 goto out;
7153
7154 name = X509_get_subject_name(crt);
7155 if (!name)
7156 goto out;
7157
Willy Tarreau47ca5452012-12-23 20:22:19 +01007158 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007159 if (args && args[0].type == ARGT_STR) {
7160 int pos = 1;
7161
7162 if (args[1].type == ARGT_SINT)
7163 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007164
7165 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7166 goto out;
7167 }
7168 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7169 goto out;
7170
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007171 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007172 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007173 ret = 1;
7174out:
Emeric Brunba841a12014-04-30 17:05:08 +02007175 /* SSL_get_peer_certificate, it increase X509 * ref count */
7176 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007177 X509_free(crt);
7178 return ret;
7179}
Emeric Brun9143d372012-12-20 15:44:16 +01007180
7181/* integer, returns true if current session use a client certificate */
7182static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007183smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007184{
7185 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007186 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007187 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007188
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007189 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007190 if (!conn || conn->xprt != &ssl_sock)
7191 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007192 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007193
7194 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007195 smp->flags |= SMP_F_MAY_CHANGE;
7196 return 0;
7197 }
7198
7199 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007200 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007201 if (crt) {
7202 X509_free(crt);
7203 }
7204
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007205 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007206 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007207 return 1;
7208}
7209
Emeric Brunba841a12014-04-30 17:05:08 +02007210/* integer, returns the certificate version
7211 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7212 * should be use.
7213 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007214static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007215smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007216{
Emeric Brunba841a12014-04-30 17:05:08 +02007217 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007218 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007219 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007220 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007221
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007222 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007223 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007224 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007225 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007226
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007227 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007228 smp->flags |= SMP_F_MAY_CHANGE;
7229 return 0;
7230 }
7231
Emeric Brunba841a12014-04-30 17:05:08 +02007232 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007233 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007234 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007235 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007236 if (!crt)
7237 return 0;
7238
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007239 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007240 /* SSL_get_peer_certificate increase X509 * ref count */
7241 if (cert_peer)
7242 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007243 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007244
7245 return 1;
7246}
7247
Emeric Brunba841a12014-04-30 17:05:08 +02007248/* string, returns the certificate's signature algorithm.
7249 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7250 * should be use.
7251 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007252static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007253smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007254{
Emeric Brunba841a12014-04-30 17:05:08 +02007255 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007256 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007257 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007258 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007259 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007260 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007261
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007262 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007263 if (!conn || conn->xprt != &ssl_sock)
7264 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007265 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007266
7267 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007268 smp->flags |= SMP_F_MAY_CHANGE;
7269 return 0;
7270 }
7271
Emeric Brunba841a12014-04-30 17:05:08 +02007272 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007273 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007274 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007275 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007276 if (!crt)
7277 return 0;
7278
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007279 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7280 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007281
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007282 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7283 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007284 /* SSL_get_peer_certificate increase X509 * ref count */
7285 if (cert_peer)
7286 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007287 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007288 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007289
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007290 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007291 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007292 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007293 /* SSL_get_peer_certificate increase X509 * ref count */
7294 if (cert_peer)
7295 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007296
7297 return 1;
7298}
7299
Emeric Brunba841a12014-04-30 17:05:08 +02007300/* string, returns the certificate's key algorithm.
7301 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7302 * should be use.
7303 */
Emeric Brun521a0112012-10-22 12:22:55 +02007304static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007305smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007306{
Emeric Brunba841a12014-04-30 17:05:08 +02007307 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007308 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007309 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007310 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007311 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007312 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007313
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007314 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007315 if (!conn || conn->xprt != &ssl_sock)
7316 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007317 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007318
7319 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007320 smp->flags |= SMP_F_MAY_CHANGE;
7321 return 0;
7322 }
7323
Emeric Brunba841a12014-04-30 17:05:08 +02007324 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007325 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007326 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007327 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007328 if (!crt)
7329 return 0;
7330
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007331 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7332 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007333
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007334 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7335 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007336 /* SSL_get_peer_certificate increase X509 * ref count */
7337 if (cert_peer)
7338 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007339 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007340 }
Emeric Brun521a0112012-10-22 12:22:55 +02007341
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007342 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007343 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007344 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007345 if (cert_peer)
7346 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007347
7348 return 1;
7349}
7350
Emeric Brun645ae792014-04-30 14:21:06 +02007351/* boolean, returns true if front conn. transport layer is SSL.
7352 * This function is also usable on backend conn if the fetch keyword 5th
7353 * char is 'b'.
7354 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007355static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007356smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007357{
Emeric Bruneb8def92018-02-19 15:59:48 +01007358 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7359 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007360
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007361 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007362 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007363 return 1;
7364}
7365
Emeric Brun2525b6b2012-10-18 15:59:43 +02007366/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007367static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007368smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007369{
7370#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007371 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007372 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007373
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007374 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007375 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007376 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007377 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007378 return 1;
7379#else
7380 return 0;
7381#endif
7382}
7383
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007384/* boolean, returns true if client session has been resumed.
7385 * This function is also usable on backend conn if the fetch keyword 5th
7386 * char is 'b'.
7387 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007388static int
7389smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7390{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007391 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7392 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007393 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007394
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007395
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007396 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007397 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007398 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007399 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007400 return 1;
7401}
7402
Emeric Brun645ae792014-04-30 14:21:06 +02007403/* string, returns the used cipher if front conn. transport layer is SSL.
7404 * This function is also usable on backend conn if the fetch keyword 5th
7405 * char is 'b'.
7406 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007407static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007408smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007409{
Emeric Bruneb8def92018-02-19 15:59:48 +01007410 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7411 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007412 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007413
Willy Tarreaube508f12016-03-10 11:47:01 +01007414 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007415 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007416 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007417 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007418
Olivier Houchard66ab4982019-02-26 18:37:15 +01007419 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007420 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007421 return 0;
7422
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007423 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007424 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007425 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007426
7427 return 1;
7428}
7429
Emeric Brun645ae792014-04-30 14:21:06 +02007430/* integer, returns the algoritm's keysize if front conn. transport layer
7431 * is SSL.
7432 * This function is also usable on backend conn if the fetch keyword 5th
7433 * char is 'b'.
7434 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007435static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007436smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007437{
Emeric Bruneb8def92018-02-19 15:59:48 +01007438 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7439 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007440 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007441 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007442
Emeric Brun589fcad2012-10-16 14:13:26 +02007443 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007444 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007445 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007446 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007447
Olivier Houchard66ab4982019-02-26 18:37:15 +01007448 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007449 return 0;
7450
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007451 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007452 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007453
7454 return 1;
7455}
7456
Emeric Brun645ae792014-04-30 14:21:06 +02007457/* integer, returns the used keysize if front conn. transport layer is SSL.
7458 * This function is also usable on backend conn if the fetch keyword 5th
7459 * char is 'b'.
7460 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007461static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007462smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007463{
Emeric Bruneb8def92018-02-19 15:59:48 +01007464 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7465 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007466 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007467
Emeric Brun589fcad2012-10-16 14:13:26 +02007468 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007469 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7470 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007471 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007472
Olivier Houchard66ab4982019-02-26 18:37:15 +01007473 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007474 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007475 return 0;
7476
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007477 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007478
7479 return 1;
7480}
7481
Bernard Spil13c53f82018-02-15 13:34:58 +01007482#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007483static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007484smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007485{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007486 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007487 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007488
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007489 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007490 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007491
Olivier Houchard6b77f492018-11-22 18:18:29 +01007492 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7493 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007494 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7495 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007496 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007497
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007498 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007499 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007500 (const unsigned char **)&smp->data.u.str.area,
7501 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007502
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007503 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007504 return 0;
7505
7506 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007507}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007508#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007509
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007510#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007511static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007512smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007513{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007514 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007515 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007516
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007517 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007518 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007519
Olivier Houchard6b77f492018-11-22 18:18:29 +01007520 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7521 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7522
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007523 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007524 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007525 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007526
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007527 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007528 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007529 (const unsigned char **)&smp->data.u.str.area,
7530 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007531
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007532 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007533 return 0;
7534
7535 return 1;
7536}
7537#endif
7538
Emeric Brun645ae792014-04-30 14:21:06 +02007539/* string, returns the used protocol if front conn. transport layer is SSL.
7540 * This function is also usable on backend conn if the fetch keyword 5th
7541 * char is 'b'.
7542 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007543static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007544smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007545{
Emeric Bruneb8def92018-02-19 15:59:48 +01007546 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7547 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007548 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007549
Emeric Brun589fcad2012-10-16 14:13:26 +02007550 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007551 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7552 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007553 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007554
Olivier Houchard66ab4982019-02-26 18:37:15 +01007555 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007556 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007557 return 0;
7558
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007559 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007560 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007561 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007562
7563 return 1;
7564}
7565
Willy Tarreau87b09662015-04-03 00:22:06 +02007566/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007567 * This function is also usable on backend conn if the fetch keyword 5th
7568 * char is 'b'.
7569 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007570#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007571static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007572smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007573{
Emeric Bruneb8def92018-02-19 15:59:48 +01007574 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7575 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007576 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007577 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007578
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007579 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007580 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007581
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007582 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7583 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007584 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007585
Olivier Houchard66ab4982019-02-26 18:37:15 +01007586 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007587 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007588 return 0;
7589
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007590 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7591 (unsigned int *)&smp->data.u.str.data);
7592 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007593 return 0;
7594
7595 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007596}
Patrick Hemmer41966772018-04-28 19:15:48 -04007597#endif
7598
Emeric Brunfe68f682012-10-16 14:59:28 +02007599
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007600#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007601static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007602smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7603{
7604 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7605 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7606 struct buffer *data;
7607 struct ssl_sock_ctx *ctx;
7608
7609 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7610 return 0;
7611 ctx = conn->xprt_ctx;
7612
7613 data = get_trash_chunk();
7614 if (kw[7] == 'c')
7615 data->data = SSL_get_client_random(ctx->ssl,
7616 (unsigned char *) data->area,
7617 data->size);
7618 else
7619 data->data = SSL_get_server_random(ctx->ssl,
7620 (unsigned char *) data->area,
7621 data->size);
7622 if (!data->data)
7623 return 0;
7624
7625 smp->flags = 0;
7626 smp->data.type = SMP_T_BIN;
7627 smp->data.u.str = *data;
7628
7629 return 1;
7630}
7631
7632static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007633smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7634{
7635 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7636 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7637 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007638 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007639 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007640
7641 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7642 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007643 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007644
Olivier Houchard66ab4982019-02-26 18:37:15 +01007645 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007646 if (!ssl_sess)
7647 return 0;
7648
7649 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007650 data->data = SSL_SESSION_get_master_key(ssl_sess,
7651 (unsigned char *) data->area,
7652 data->size);
7653 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007654 return 0;
7655
7656 smp->flags = 0;
7657 smp->data.type = SMP_T_BIN;
7658 smp->data.u.str = *data;
7659
7660 return 1;
7661}
7662#endif
7663
Patrick Hemmer41966772018-04-28 19:15:48 -04007664#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007665static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007666smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007667{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007668 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007669 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007670
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007671 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007672 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007673
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007674 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007675 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7676 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007677 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007678
Olivier Houchard66ab4982019-02-26 18:37:15 +01007679 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007680 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007681 return 0;
7682
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007683 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007684 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007685}
Patrick Hemmer41966772018-04-28 19:15:48 -04007686#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007687
David Sc1ad52e2014-04-08 18:48:47 -04007688static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007689smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7690{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007691 struct connection *conn;
7692 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007693 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007694
7695 conn = objt_conn(smp->sess->origin);
7696 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7697 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007698 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007699
Olivier Houchard66ab4982019-02-26 18:37:15 +01007700 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007701 if (!capture)
7702 return 0;
7703
7704 smp->flags = SMP_F_CONST;
7705 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007706 smp->data.u.str.area = capture->ciphersuite;
7707 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007708 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007709}
7710
7711static int
7712smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7713{
Willy Tarreau83061a82018-07-13 11:56:34 +02007714 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007715
7716 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7717 return 0;
7718
7719 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007720 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007721 smp->data.type = SMP_T_BIN;
7722 smp->data.u.str = *data;
7723 return 1;
7724}
7725
7726static int
7727smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7728{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007729 struct connection *conn;
7730 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007731 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007732
7733 conn = objt_conn(smp->sess->origin);
7734 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7735 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007736 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007737
Olivier Houchard66ab4982019-02-26 18:37:15 +01007738 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007739 if (!capture)
7740 return 0;
7741
7742 smp->data.type = SMP_T_SINT;
7743 smp->data.u.sint = capture->xxh64;
7744 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007745}
7746
7747static int
7748smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7749{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007750#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007751 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007752 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007753
7754 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7755 return 0;
7756
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007757 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007758 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007759 const char *str;
7760 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007761 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007762 uint16_t id = (bin[0] << 8) | bin[1];
7763#if defined(OPENSSL_IS_BORINGSSL)
7764 cipher = SSL_get_cipher_by_value(id);
7765#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007766 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007767 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7768 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007769#endif
7770 str = SSL_CIPHER_get_name(cipher);
7771 if (!str || strcmp(str, "(NONE)") == 0)
7772 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007773 else
7774 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7775 }
7776 smp->data.type = SMP_T_STR;
7777 smp->data.u.str = *data;
7778 return 1;
7779#else
7780 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7781#endif
7782}
7783
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007784#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007785static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007786smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007787{
Emeric Bruneb8def92018-02-19 15:59:48 +01007788 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7789 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007790 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007791 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007792 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007793
7794 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007795 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7796 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007797 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007798
7799 if (!(conn->flags & CO_FL_CONNECTED)) {
7800 smp->flags |= SMP_F_MAY_CHANGE;
7801 return 0;
7802 }
7803
7804 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007805 if (!SSL_session_reused(ctx->ssl))
7806 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007807 finished_trash->area,
7808 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007809 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007810 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007811 finished_trash->area,
7812 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007813
7814 if (!finished_len)
7815 return 0;
7816
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007817 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007818 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007819 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007820
7821 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007822}
Patrick Hemmer41966772018-04-28 19:15:48 -04007823#endif
David Sc1ad52e2014-04-08 18:48:47 -04007824
Emeric Brun2525b6b2012-10-18 15:59:43 +02007825/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007826static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007827smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007828{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007829 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007830 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007831
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007832 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007833 if (!conn || conn->xprt != &ssl_sock)
7834 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007835 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007836
7837 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007838 smp->flags = SMP_F_MAY_CHANGE;
7839 return 0;
7840 }
7841
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007842 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007843 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007844 smp->flags = 0;
7845
7846 return 1;
7847}
7848
Emeric Brun2525b6b2012-10-18 15:59:43 +02007849/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007850static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007851smp_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 +02007852{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007853 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007854 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007855
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007856 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007857 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007858 return 0;
7859
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007860 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007861 smp->flags = SMP_F_MAY_CHANGE;
7862 return 0;
7863 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007864 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007865
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007866 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007867 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007868 smp->flags = 0;
7869
7870 return 1;
7871}
7872
Emeric Brun2525b6b2012-10-18 15:59:43 +02007873/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007874static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007875smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007876{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007877 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007878 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007879
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007880 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007881 if (!conn || conn->xprt != &ssl_sock)
7882 return 0;
7883
7884 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007885 smp->flags = SMP_F_MAY_CHANGE;
7886 return 0;
7887 }
7888
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007889 ctx = conn->xprt_ctx;
7890
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007891 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007892 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007893 smp->flags = 0;
7894
7895 return 1;
7896}
7897
Emeric Brun2525b6b2012-10-18 15:59:43 +02007898/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007899static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007900smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007901{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007902 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007903 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007904
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007905 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007906 if (!conn || conn->xprt != &ssl_sock)
7907 return 0;
7908
7909 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007910 smp->flags = SMP_F_MAY_CHANGE;
7911 return 0;
7912 }
7913
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007914 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007915 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007916 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007917
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007918 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007919 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007920 smp->flags = 0;
7921
7922 return 1;
7923}
7924
Emeric Brunfb510ea2012-10-05 12:00:26 +02007925/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007926static 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 +02007927{
7928 if (!*args[cur_arg + 1]) {
7929 if (err)
7930 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7931 return ERR_ALERT | ERR_FATAL;
7932 }
7933
Willy Tarreauef934602016-12-22 23:12:01 +01007934 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7935 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007936 else
7937 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007938
Emeric Brund94b3fe2012-09-20 18:23:56 +02007939 return 0;
7940}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007941static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7942{
7943 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7944}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007945
Christopher Faulet31af49d2015-06-09 17:29:50 +02007946/* parse the "ca-sign-file" bind keyword */
7947static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7948{
7949 if (!*args[cur_arg + 1]) {
7950 if (err)
7951 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7952 return ERR_ALERT | ERR_FATAL;
7953 }
7954
Willy Tarreauef934602016-12-22 23:12:01 +01007955 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7956 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007957 else
7958 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7959
7960 return 0;
7961}
7962
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007963/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007964static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7965{
7966 if (!*args[cur_arg + 1]) {
7967 if (err)
7968 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7969 return ERR_ALERT | ERR_FATAL;
7970 }
7971 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7972 return 0;
7973}
7974
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007975/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007976static 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 +02007977{
7978 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007979 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007980 return ERR_ALERT | ERR_FATAL;
7981 }
7982
Emeric Brun76d88952012-10-05 15:47:31 +02007983 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007984 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007985 return 0;
7986}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007987static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7988{
7989 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7990}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007991
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007992#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007993/* parse the "ciphersuites" bind keyword */
7994static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7995{
7996 if (!*args[cur_arg + 1]) {
7997 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7998 return ERR_ALERT | ERR_FATAL;
7999 }
8000
8001 free(conf->ciphersuites);
8002 conf->ciphersuites = strdup(args[cur_arg + 1]);
8003 return 0;
8004}
8005static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8006{
8007 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
8008}
8009#endif
8010
Willy Tarreaubbc91962019-10-16 16:42:19 +02008011/* parse the "crt" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008012static 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 +02008013{
Willy Tarreau38011032013-08-13 16:59:39 +02008014 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02008015
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008016 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02008017 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008018 return ERR_ALERT | ERR_FATAL;
8019 }
8020
Willy Tarreauef934602016-12-22 23:12:01 +01008021 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
8022 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02008023 memprintf(err, "'%s' : path too long", args[cur_arg]);
8024 return ERR_ALERT | ERR_FATAL;
8025 }
Willy Tarreauef934602016-12-22 23:12:01 +01008026 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreaubbc91962019-10-16 16:42:19 +02008027 return ssl_sock_load_cert(path, conf, err);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008028 }
8029
Willy Tarreaubbc91962019-10-16 16:42:19 +02008030 return ssl_sock_load_cert(args[cur_arg + 1], conf, err);
Emeric Brund94b3fe2012-09-20 18:23:56 +02008031}
8032
Willy Tarreaubbc91962019-10-16 16:42:19 +02008033/* parse the "crt-list" bind keyword. Returns a set of ERR_* flags possibly with an error in <err>. */
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008034static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8035{
Willy Tarreaubbc91962019-10-16 16:42:19 +02008036 int err_code;
8037
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008038 if (!*args[cur_arg + 1]) {
8039 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8040 return ERR_ALERT | ERR_FATAL;
8041 }
8042
Willy Tarreaubbc91962019-10-16 16:42:19 +02008043 err_code = ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err);
8044 if (err_code)
Willy Tarreauad1731d2013-04-02 17:35:58 +02008045 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008046
Willy Tarreaubbc91962019-10-16 16:42:19 +02008047 return err_code;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008048}
8049
Emeric Brunfb510ea2012-10-05 12:00:26 +02008050/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008051static 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 +02008052{
Emeric Brun051cdab2012-10-02 19:25:50 +02008053#ifndef X509_V_FLAG_CRL_CHECK
8054 if (err)
8055 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8056 return ERR_ALERT | ERR_FATAL;
8057#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008058 if (!*args[cur_arg + 1]) {
8059 if (err)
8060 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8061 return ERR_ALERT | ERR_FATAL;
8062 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008063
Willy Tarreauef934602016-12-22 23:12:01 +01008064 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8065 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008066 else
8067 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008068
Emeric Brun2b58d042012-09-20 17:10:03 +02008069 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008070#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008071}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008072static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8073{
8074 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8075}
Emeric Brun2b58d042012-09-20 17:10:03 +02008076
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008077/* parse the "curves" bind keyword keyword */
8078static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8079{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008080#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008081 if (!*args[cur_arg + 1]) {
8082 if (err)
8083 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8084 return ERR_ALERT | ERR_FATAL;
8085 }
8086 conf->curves = strdup(args[cur_arg + 1]);
8087 return 0;
8088#else
8089 if (err)
8090 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8091 return ERR_ALERT | ERR_FATAL;
8092#endif
8093}
8094static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8095{
8096 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8097}
8098
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008099/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008100static 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 +02008101{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008102#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008103 if (err)
8104 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8105 return ERR_ALERT | ERR_FATAL;
8106#elif defined(OPENSSL_NO_ECDH)
8107 if (err)
8108 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8109 return ERR_ALERT | ERR_FATAL;
8110#else
8111 if (!*args[cur_arg + 1]) {
8112 if (err)
8113 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8114 return ERR_ALERT | ERR_FATAL;
8115 }
8116
8117 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008118
8119 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008120#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008121}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008122static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8123{
8124 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8125}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008126
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008127/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008128static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8129{
8130 int code;
8131 char *p = args[cur_arg + 1];
8132 unsigned long long *ignerr = &conf->crt_ignerr;
8133
8134 if (!*p) {
8135 if (err)
8136 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8137 return ERR_ALERT | ERR_FATAL;
8138 }
8139
8140 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8141 ignerr = &conf->ca_ignerr;
8142
8143 if (strcmp(p, "all") == 0) {
8144 *ignerr = ~0ULL;
8145 return 0;
8146 }
8147
8148 while (p) {
8149 code = atoi(p);
8150 if ((code <= 0) || (code > 63)) {
8151 if (err)
8152 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8153 args[cur_arg], code, args[cur_arg + 1]);
8154 return ERR_ALERT | ERR_FATAL;
8155 }
8156 *ignerr |= 1ULL << code;
8157 p = strchr(p, ',');
8158 if (p)
8159 p++;
8160 }
8161
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008162 return 0;
8163}
8164
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008165/* parse tls_method_options "no-xxx" and "force-xxx" */
8166static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008167{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008168 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008169 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008170 p = strchr(arg, '-');
8171 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008172 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008173 p++;
8174 if (!strcmp(p, "sslv3"))
8175 v = CONF_SSLV3;
8176 else if (!strcmp(p, "tlsv10"))
8177 v = CONF_TLSV10;
8178 else if (!strcmp(p, "tlsv11"))
8179 v = CONF_TLSV11;
8180 else if (!strcmp(p, "tlsv12"))
8181 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008182 else if (!strcmp(p, "tlsv13"))
8183 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008184 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008185 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008186 if (!strncmp(arg, "no-", 3))
8187 methods->flags |= methodVersions[v].flag;
8188 else if (!strncmp(arg, "force-", 6))
8189 methods->min = methods->max = v;
8190 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008191 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008192 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008193 fail:
8194 if (err)
8195 memprintf(err, "'%s' : option not implemented", arg);
8196 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008197}
8198
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008199static 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 +02008200{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008201 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008202}
8203
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008204static 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 +02008205{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008206 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8207}
8208
8209/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8210static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8211{
8212 uint16_t i, v = 0;
8213 char *argv = args[cur_arg + 1];
8214 if (!*argv) {
8215 if (err)
8216 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8217 return ERR_ALERT | ERR_FATAL;
8218 }
8219 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8220 if (!strcmp(argv, methodVersions[i].name))
8221 v = i;
8222 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008223 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008224 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008225 return ERR_ALERT | ERR_FATAL;
8226 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008227 if (!strcmp("ssl-min-ver", args[cur_arg]))
8228 methods->min = v;
8229 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8230 methods->max = v;
8231 else {
8232 if (err)
8233 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8234 return ERR_ALERT | ERR_FATAL;
8235 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008236 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008237}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008238
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008239static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8240{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008241#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008242 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 +02008243#endif
8244 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8245}
8246
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008247static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8248{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008249 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008250}
8251
8252static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8253{
8254 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8255}
8256
Emeric Brun2d0c4822012-10-02 13:45:20 +02008257/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008258static 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 +02008259{
Emeric Brun89675492012-10-05 13:48:26 +02008260 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008261 return 0;
8262}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008263
Olivier Houchardc2aae742017-09-22 18:26:28 +02008264/* parse the "allow-0rtt" bind keyword */
8265static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8266{
8267 conf->early_data = 1;
8268 return 0;
8269}
8270
8271static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8272{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008273 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008274 return 0;
8275}
8276
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008277/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008278static 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 +02008279{
Bernard Spil13c53f82018-02-15 13:34:58 +01008280#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008281 char *p1, *p2;
8282
8283 if (!*args[cur_arg + 1]) {
8284 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8285 return ERR_ALERT | ERR_FATAL;
8286 }
8287
8288 free(conf->npn_str);
8289
Willy Tarreau3724da12016-02-12 17:11:12 +01008290 /* the NPN string is built as a suite of (<len> <name>)*,
8291 * so we reuse each comma to store the next <len> and need
8292 * one more for the end of the string.
8293 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008294 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008295 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008296 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8297
8298 /* replace commas with the name length */
8299 p1 = conf->npn_str;
8300 p2 = p1 + 1;
8301 while (1) {
8302 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8303 if (!p2)
8304 p2 = p1 + 1 + strlen(p1 + 1);
8305
8306 if (p2 - (p1 + 1) > 255) {
8307 *p2 = '\0';
8308 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8309 return ERR_ALERT | ERR_FATAL;
8310 }
8311
8312 *p1 = p2 - (p1 + 1);
8313 p1 = p2;
8314
8315 if (!*p2)
8316 break;
8317
8318 *(p2++) = '\0';
8319 }
8320 return 0;
8321#else
8322 if (err)
8323 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8324 return ERR_ALERT | ERR_FATAL;
8325#endif
8326}
8327
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008328static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8329{
8330 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8331}
8332
Willy Tarreauab861d32013-04-02 02:30:41 +02008333/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008334static 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 +02008335{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008336#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008337 char *p1, *p2;
8338
8339 if (!*args[cur_arg + 1]) {
8340 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8341 return ERR_ALERT | ERR_FATAL;
8342 }
8343
8344 free(conf->alpn_str);
8345
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008346 /* the ALPN string is built as a suite of (<len> <name>)*,
8347 * so we reuse each comma to store the next <len> and need
8348 * one more for the end of the string.
8349 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008350 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008351 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008352 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8353
8354 /* replace commas with the name length */
8355 p1 = conf->alpn_str;
8356 p2 = p1 + 1;
8357 while (1) {
8358 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8359 if (!p2)
8360 p2 = p1 + 1 + strlen(p1 + 1);
8361
8362 if (p2 - (p1 + 1) > 255) {
8363 *p2 = '\0';
8364 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8365 return ERR_ALERT | ERR_FATAL;
8366 }
8367
8368 *p1 = p2 - (p1 + 1);
8369 p1 = p2;
8370
8371 if (!*p2)
8372 break;
8373
8374 *(p2++) = '\0';
8375 }
8376 return 0;
8377#else
8378 if (err)
8379 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8380 return ERR_ALERT | ERR_FATAL;
8381#endif
8382}
8383
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008384static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8385{
8386 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8387}
8388
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008389/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008390static 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 +02008391{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008392 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008393 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008394
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008395 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8396 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008397#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008398 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8399 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8400#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008401 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008402 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8403 if (!conf->ssl_conf.ssl_methods.min)
8404 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8405 if (!conf->ssl_conf.ssl_methods.max)
8406 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008407
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008408 return 0;
8409}
8410
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008411/* parse the "prefer-client-ciphers" bind keyword */
8412static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8413{
8414 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8415 return 0;
8416}
8417
Christopher Faulet31af49d2015-06-09 17:29:50 +02008418/* parse the "generate-certificates" bind keyword */
8419static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8420{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008421#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008422 conf->generate_certs = 1;
8423#else
8424 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8425 err && *err ? *err : "");
8426#endif
8427 return 0;
8428}
8429
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008430/* parse the "strict-sni" bind keyword */
8431static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8432{
8433 conf->strict_sni = 1;
8434 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008435}
8436
8437/* parse the "tls-ticket-keys" bind keyword */
8438static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8439{
8440#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8441 FILE *f;
8442 int i = 0;
8443 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008444 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008445
8446 if (!*args[cur_arg + 1]) {
8447 if (err)
8448 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
8449 return ERR_ALERT | ERR_FATAL;
8450 }
8451
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008452 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008453 if (keys_ref) {
8454 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008455 conf->keys_ref = keys_ref;
8456 return 0;
8457 }
8458
Vincent Bernat02779b62016-04-03 13:48:43 +02008459 keys_ref = malloc(sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008460 if (!keys_ref) {
8461 if (err)
8462 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8463 return ERR_ALERT | ERR_FATAL;
8464 }
8465
Emeric Brun9e754772019-01-10 17:51:55 +01008466 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008467 if (!keys_ref->tlskeys) {
8468 free(keys_ref);
8469 if (err)
8470 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8471 return ERR_ALERT | ERR_FATAL;
8472 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008473
8474 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Emeric Brun09852f72019-01-10 10:51:13 +01008475 free(keys_ref->tlskeys);
8476 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008477 if (err)
8478 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
8479 return ERR_ALERT | ERR_FATAL;
8480 }
8481
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008482 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008483 if (!keys_ref->filename) {
8484 free(keys_ref->tlskeys);
8485 free(keys_ref);
8486 if (err)
8487 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8488 return ERR_ALERT | ERR_FATAL;
8489 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008490
Emeric Brun9e754772019-01-10 17:51:55 +01008491 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008492 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8493 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008494 int dec_size;
8495
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008496 /* Strip newline characters from the end */
8497 if(thisline[len - 1] == '\n')
8498 thisline[--len] = 0;
8499
8500 if(thisline[len - 1] == '\r')
8501 thisline[--len] = 0;
8502
Emeric Brun9e754772019-01-10 17:51:55 +01008503 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8504 if (dec_size < 0) {
Emeric Brun09852f72019-01-10 10:51:13 +01008505 free(keys_ref->filename);
8506 free(keys_ref->tlskeys);
8507 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008508 if (err)
8509 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02008510 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008511 return ERR_ALERT | ERR_FATAL;
8512 }
Emeric Brun9e754772019-01-10 17:51:55 +01008513 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8514 keys_ref->key_size_bits = 128;
8515 }
8516 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8517 keys_ref->key_size_bits = 256;
8518 }
8519 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8520 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8521 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
8522 free(keys_ref->filename);
8523 free(keys_ref->tlskeys);
8524 free(keys_ref);
8525 if (err)
8526 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
8527 fclose(f);
8528 return ERR_ALERT | ERR_FATAL;
8529 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008530 i++;
8531 }
8532
8533 if (i < TLS_TICKETS_NO) {
Emeric Brun09852f72019-01-10 10:51:13 +01008534 free(keys_ref->filename);
8535 free(keys_ref->tlskeys);
8536 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008537 if (err)
8538 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 +02008539 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008540 return ERR_ALERT | ERR_FATAL;
8541 }
8542
8543 fclose(f);
8544
8545 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008546 i -= 2;
8547 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008548 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008549 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008550 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008551 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008552
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008553 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8554
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008555 return 0;
8556#else
8557 if (err)
8558 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8559 return ERR_ALERT | ERR_FATAL;
8560#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008561}
8562
Emeric Brund94b3fe2012-09-20 18:23:56 +02008563/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008564static 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 +02008565{
8566 if (!*args[cur_arg + 1]) {
8567 if (err)
8568 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8569 return ERR_ALERT | ERR_FATAL;
8570 }
8571
8572 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008573 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008574 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008575 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008576 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008577 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008578 else {
8579 if (err)
8580 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8581 args[cur_arg], args[cur_arg + 1]);
8582 return ERR_ALERT | ERR_FATAL;
8583 }
8584
8585 return 0;
8586}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008587static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8588{
8589 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8590}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008591
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008592/* parse the "no-ca-names" bind keyword */
8593static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8594{
8595 conf->no_ca_names = 1;
8596 return 0;
8597}
8598static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8599{
8600 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8601}
8602
Willy Tarreau92faadf2012-10-10 23:04:25 +02008603/************** "server" keywords ****************/
8604
Olivier Houchardc7566002018-11-20 23:33:50 +01008605/* parse the "npn" bind keyword */
8606static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8607{
8608#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8609 char *p1, *p2;
8610
8611 if (!*args[*cur_arg + 1]) {
8612 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8613 return ERR_ALERT | ERR_FATAL;
8614 }
8615
8616 free(newsrv->ssl_ctx.npn_str);
8617
8618 /* the NPN string is built as a suite of (<len> <name>)*,
8619 * so we reuse each comma to store the next <len> and need
8620 * one more for the end of the string.
8621 */
8622 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8623 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8624 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8625 newsrv->ssl_ctx.npn_len);
8626
8627 /* replace commas with the name length */
8628 p1 = newsrv->ssl_ctx.npn_str;
8629 p2 = p1 + 1;
8630 while (1) {
8631 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8632 newsrv->ssl_ctx.npn_len - (p1 + 1));
8633 if (!p2)
8634 p2 = p1 + 1 + strlen(p1 + 1);
8635
8636 if (p2 - (p1 + 1) > 255) {
8637 *p2 = '\0';
8638 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8639 return ERR_ALERT | ERR_FATAL;
8640 }
8641
8642 *p1 = p2 - (p1 + 1);
8643 p1 = p2;
8644
8645 if (!*p2)
8646 break;
8647
8648 *(p2++) = '\0';
8649 }
8650 return 0;
8651#else
8652 if (err)
8653 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8654 return ERR_ALERT | ERR_FATAL;
8655#endif
8656}
8657
Olivier Houchard92150142018-12-21 19:47:01 +01008658/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008659static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8660{
8661#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8662 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008663 char **alpn_str;
8664 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008665
Olivier Houchard92150142018-12-21 19:47:01 +01008666 if (*args[*cur_arg] == 'c') {
8667 alpn_str = &newsrv->check.alpn_str;
8668 alpn_len = &newsrv->check.alpn_len;
8669 } else {
8670 alpn_str = &newsrv->ssl_ctx.alpn_str;
8671 alpn_len = &newsrv->ssl_ctx.alpn_len;
8672
8673 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008674 if (!*args[*cur_arg + 1]) {
8675 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8676 return ERR_ALERT | ERR_FATAL;
8677 }
8678
Olivier Houchard92150142018-12-21 19:47:01 +01008679 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008680
8681 /* the ALPN string is built as a suite of (<len> <name>)*,
8682 * so we reuse each comma to store the next <len> and need
8683 * one more for the end of the string.
8684 */
Olivier Houchard92150142018-12-21 19:47:01 +01008685 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8686 *alpn_str = calloc(1, *alpn_len + 1);
8687 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008688
8689 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008690 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008691 p2 = p1 + 1;
8692 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008693 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008694 if (!p2)
8695 p2 = p1 + 1 + strlen(p1 + 1);
8696
8697 if (p2 - (p1 + 1) > 255) {
8698 *p2 = '\0';
8699 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8700 return ERR_ALERT | ERR_FATAL;
8701 }
8702
8703 *p1 = p2 - (p1 + 1);
8704 p1 = p2;
8705
8706 if (!*p2)
8707 break;
8708
8709 *(p2++) = '\0';
8710 }
8711 return 0;
8712#else
8713 if (err)
8714 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8715 return ERR_ALERT | ERR_FATAL;
8716#endif
8717}
8718
Emeric Brunef42d922012-10-11 16:11:36 +02008719/* parse the "ca-file" server keyword */
8720static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8721{
8722 if (!*args[*cur_arg + 1]) {
8723 if (err)
8724 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8725 return ERR_ALERT | ERR_FATAL;
8726 }
8727
Willy Tarreauef934602016-12-22 23:12:01 +01008728 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8729 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008730 else
8731 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8732
8733 return 0;
8734}
8735
Olivier Houchard9130a962017-10-17 17:33:43 +02008736/* parse the "check-sni" server keyword */
8737static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8738{
8739 if (!*args[*cur_arg + 1]) {
8740 if (err)
8741 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8742 return ERR_ALERT | ERR_FATAL;
8743 }
8744
8745 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8746 if (!newsrv->check.sni) {
8747 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8748 return ERR_ALERT | ERR_FATAL;
8749 }
8750 return 0;
8751
8752}
8753
Willy Tarreau92faadf2012-10-10 23:04:25 +02008754/* parse the "check-ssl" server keyword */
8755static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8756{
8757 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008758 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8759 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008760#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008761 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8762 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8763#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008764 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008765 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8766 if (!newsrv->ssl_ctx.methods.min)
8767 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8768 if (!newsrv->ssl_ctx.methods.max)
8769 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8770
Willy Tarreau92faadf2012-10-10 23:04:25 +02008771 return 0;
8772}
8773
8774/* parse the "ciphers" server keyword */
8775static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8776{
8777 if (!*args[*cur_arg + 1]) {
8778 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8779 return ERR_ALERT | ERR_FATAL;
8780 }
8781
8782 free(newsrv->ssl_ctx.ciphers);
8783 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8784 return 0;
8785}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008786
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008787#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008788/* parse the "ciphersuites" server keyword */
8789static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8790{
8791 if (!*args[*cur_arg + 1]) {
8792 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8793 return ERR_ALERT | ERR_FATAL;
8794 }
8795
8796 free(newsrv->ssl_ctx.ciphersuites);
8797 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8798 return 0;
8799}
8800#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008801
Emeric Brunef42d922012-10-11 16:11:36 +02008802/* parse the "crl-file" server keyword */
8803static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8804{
8805#ifndef X509_V_FLAG_CRL_CHECK
8806 if (err)
8807 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8808 return ERR_ALERT | ERR_FATAL;
8809#else
8810 if (!*args[*cur_arg + 1]) {
8811 if (err)
8812 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8813 return ERR_ALERT | ERR_FATAL;
8814 }
8815
Willy Tarreauef934602016-12-22 23:12:01 +01008816 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8817 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008818 else
8819 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8820
8821 return 0;
8822#endif
8823}
8824
Emeric Bruna7aa3092012-10-26 12:58:00 +02008825/* parse the "crt" server keyword */
8826static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8827{
8828 if (!*args[*cur_arg + 1]) {
8829 if (err)
8830 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8831 return ERR_ALERT | ERR_FATAL;
8832 }
8833
Willy Tarreauef934602016-12-22 23:12:01 +01008834 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008835 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008836 else
8837 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8838
8839 return 0;
8840}
Emeric Brunef42d922012-10-11 16:11:36 +02008841
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008842/* parse the "no-check-ssl" server keyword */
8843static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8844{
8845 newsrv->check.use_ssl = 0;
8846 free(newsrv->ssl_ctx.ciphers);
8847 newsrv->ssl_ctx.ciphers = NULL;
8848 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8849 return 0;
8850}
8851
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008852/* parse the "no-send-proxy-v2-ssl" server keyword */
8853static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8854{
8855 newsrv->pp_opts &= ~SRV_PP_V2;
8856 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8857 return 0;
8858}
8859
8860/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8861static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8862{
8863 newsrv->pp_opts &= ~SRV_PP_V2;
8864 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8865 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8866 return 0;
8867}
8868
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008869/* parse the "no-ssl" server keyword */
8870static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8871{
8872 newsrv->use_ssl = 0;
8873 free(newsrv->ssl_ctx.ciphers);
8874 newsrv->ssl_ctx.ciphers = NULL;
8875 return 0;
8876}
8877
Olivier Houchard522eea72017-11-03 16:27:47 +01008878/* parse the "allow-0rtt" server keyword */
8879static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8880{
8881 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8882 return 0;
8883}
8884
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008885/* parse the "no-ssl-reuse" server keyword */
8886static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8887{
8888 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8889 return 0;
8890}
8891
Emeric Brunf9c5c472012-10-11 15:28:34 +02008892/* parse the "no-tls-tickets" server keyword */
8893static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8894{
8895 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8896 return 0;
8897}
David Safb76832014-05-08 23:42:08 -04008898/* parse the "send-proxy-v2-ssl" server keyword */
8899static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8900{
8901 newsrv->pp_opts |= SRV_PP_V2;
8902 newsrv->pp_opts |= SRV_PP_V2_SSL;
8903 return 0;
8904}
8905
8906/* parse the "send-proxy-v2-ssl-cn" server keyword */
8907static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8908{
8909 newsrv->pp_opts |= SRV_PP_V2;
8910 newsrv->pp_opts |= SRV_PP_V2_SSL;
8911 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8912 return 0;
8913}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008914
Willy Tarreau732eac42015-07-09 11:40:25 +02008915/* parse the "sni" server keyword */
8916static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8917{
8918#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8919 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8920 return ERR_ALERT | ERR_FATAL;
8921#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008922 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008923
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008924 arg = args[*cur_arg + 1];
8925 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008926 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8927 return ERR_ALERT | ERR_FATAL;
8928 }
8929
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008930 free(newsrv->sni_expr);
8931 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008932
Willy Tarreau732eac42015-07-09 11:40:25 +02008933 return 0;
8934#endif
8935}
8936
Willy Tarreau92faadf2012-10-10 23:04:25 +02008937/* parse the "ssl" server keyword */
8938static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8939{
8940 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008941 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8942 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008943#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008944 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8945 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8946#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008947 return 0;
8948}
8949
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008950/* parse the "ssl-reuse" server keyword */
8951static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8952{
8953 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8954 return 0;
8955}
8956
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008957/* parse the "tls-tickets" server keyword */
8958static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8959{
8960 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8961 return 0;
8962}
8963
Emeric Brunef42d922012-10-11 16:11:36 +02008964/* parse the "verify" server keyword */
8965static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8966{
8967 if (!*args[*cur_arg + 1]) {
8968 if (err)
8969 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8970 return ERR_ALERT | ERR_FATAL;
8971 }
8972
8973 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008974 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008975 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008976 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008977 else {
8978 if (err)
8979 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8980 args[*cur_arg], args[*cur_arg + 1]);
8981 return ERR_ALERT | ERR_FATAL;
8982 }
8983
Evan Broderbe554312013-06-27 00:05:25 -07008984 return 0;
8985}
8986
8987/* parse the "verifyhost" server keyword */
8988static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8989{
8990 if (!*args[*cur_arg + 1]) {
8991 if (err)
8992 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8993 return ERR_ALERT | ERR_FATAL;
8994 }
8995
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008996 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008997 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8998
Emeric Brunef42d922012-10-11 16:11:36 +02008999 return 0;
9000}
9001
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009002/* parse the "ssl-default-bind-options" keyword in global section */
9003static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
9004 struct proxy *defpx, const char *file, int line,
9005 char **err) {
9006 int i = 1;
9007
9008 if (*(args[i]) == 0) {
9009 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9010 return -1;
9011 }
9012 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009013 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009014 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00009015 else if (!strcmp(args[i], "prefer-client-ciphers"))
9016 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009017 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9018 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
9019 i++;
9020 else {
9021 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9022 return -1;
9023 }
9024 }
9025 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009026 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9027 return -1;
9028 }
9029 i++;
9030 }
9031 return 0;
9032}
9033
9034/* parse the "ssl-default-server-options" keyword in global section */
9035static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9036 struct proxy *defpx, const char *file, int line,
9037 char **err) {
9038 int i = 1;
9039
9040 if (*(args[i]) == 0) {
9041 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9042 return -1;
9043 }
9044 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009045 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009046 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009047 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9048 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9049 i++;
9050 else {
9051 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9052 return -1;
9053 }
9054 }
9055 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009056 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9057 return -1;
9058 }
9059 i++;
9060 }
9061 return 0;
9062}
9063
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009064/* parse the "ca-base" / "crt-base" keywords in global section.
9065 * Returns <0 on alert, >0 on warning, 0 on success.
9066 */
9067static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9068 struct proxy *defpx, const char *file, int line,
9069 char **err)
9070{
9071 char **target;
9072
Willy Tarreauef934602016-12-22 23:12:01 +01009073 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009074
9075 if (too_many_args(1, args, err, NULL))
9076 return -1;
9077
9078 if (*target) {
9079 memprintf(err, "'%s' already specified.", args[0]);
9080 return -1;
9081 }
9082
9083 if (*(args[1]) == 0) {
9084 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9085 return -1;
9086 }
9087 *target = strdup(args[1]);
9088 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009089}
9090
9091/* parse the "ssl-mode-async" keyword in global section.
9092 * Returns <0 on alert, >0 on warning, 0 on success.
9093 */
9094static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9095 struct proxy *defpx, const char *file, int line,
9096 char **err)
9097{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009098#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009099 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009100 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009101 return 0;
9102#else
9103 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9104 return -1;
9105#endif
9106}
9107
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009108#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009109static int ssl_check_async_engine_count(void) {
9110 int err_code = 0;
9111
Emeric Brun3854e012017-05-17 20:42:48 +02009112 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009113 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009114 err_code = ERR_ABORT;
9115 }
9116 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009117}
9118
Grant Zhang872f9c22017-01-21 01:10:18 +00009119/* parse the "ssl-engine" keyword in global section.
9120 * Returns <0 on alert, >0 on warning, 0 on success.
9121 */
9122static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9123 struct proxy *defpx, const char *file, int line,
9124 char **err)
9125{
9126 char *algo;
9127 int ret = -1;
9128
9129 if (*(args[1]) == 0) {
9130 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9131 return ret;
9132 }
9133
9134 if (*(args[2]) == 0) {
9135 /* if no list of algorithms is given, it defaults to ALL */
9136 algo = strdup("ALL");
9137 goto add_engine;
9138 }
9139
9140 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9141 if (strcmp(args[2], "algo") != 0) {
9142 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9143 return ret;
9144 }
9145
9146 if (*(args[3]) == 0) {
9147 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9148 return ret;
9149 }
9150 algo = strdup(args[3]);
9151
9152add_engine:
9153 if (ssl_init_single_engine(args[1], algo)==0) {
9154 openssl_engines_initialized++;
9155 ret = 0;
9156 }
9157 free(algo);
9158 return ret;
9159}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009160#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009161
Willy Tarreauf22e9682016-12-21 23:23:19 +01009162/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9163 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9164 */
9165static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9166 struct proxy *defpx, const char *file, int line,
9167 char **err)
9168{
9169 char **target;
9170
Willy Tarreauef934602016-12-22 23:12:01 +01009171 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009172
9173 if (too_many_args(1, args, err, NULL))
9174 return -1;
9175
9176 if (*(args[1]) == 0) {
9177 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9178 return -1;
9179 }
9180
9181 free(*target);
9182 *target = strdup(args[1]);
9183 return 0;
9184}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009185
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009186#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009187/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9188 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9189 */
9190static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9191 struct proxy *defpx, const char *file, int line,
9192 char **err)
9193{
9194 char **target;
9195
9196 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9197
9198 if (too_many_args(1, args, err, NULL))
9199 return -1;
9200
9201 if (*(args[1]) == 0) {
9202 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9203 return -1;
9204 }
9205
9206 free(*target);
9207 *target = strdup(args[1]);
9208 return 0;
9209}
9210#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009211
Willy Tarreau9ceda382016-12-21 23:13:03 +01009212/* parse various global tune.ssl settings consisting in positive integers.
9213 * Returns <0 on alert, >0 on warning, 0 on success.
9214 */
9215static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9216 struct proxy *defpx, const char *file, int line,
9217 char **err)
9218{
9219 int *target;
9220
9221 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9222 target = &global.tune.sslcachesize;
9223 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009224 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009225 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009226 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009227 else if (strcmp(args[0], "maxsslconn") == 0)
9228 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009229 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9230 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009231 else {
9232 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9233 return -1;
9234 }
9235
9236 if (too_many_args(1, args, err, NULL))
9237 return -1;
9238
9239 if (*(args[1]) == 0) {
9240 memprintf(err, "'%s' expects an integer argument.", args[0]);
9241 return -1;
9242 }
9243
9244 *target = atoi(args[1]);
9245 if (*target < 0) {
9246 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9247 return -1;
9248 }
9249 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009250}
9251
9252static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9253 struct proxy *defpx, const char *file, int line,
9254 char **err)
9255{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009256 int ret;
9257
9258 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9259 if (ret != 0)
9260 return ret;
9261
Willy Tarreaubafbe012017-11-24 17:34:44 +01009262 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009263 memprintf(err, "'%s' is already configured.", args[0]);
9264 return -1;
9265 }
9266
Willy Tarreaubafbe012017-11-24 17:34:44 +01009267 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9268 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009269 memprintf(err, "Out of memory error.");
9270 return -1;
9271 }
9272 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009273}
9274
9275/* parse "ssl.force-private-cache".
9276 * Returns <0 on alert, >0 on warning, 0 on success.
9277 */
9278static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9279 struct proxy *defpx, const char *file, int line,
9280 char **err)
9281{
9282 if (too_many_args(0, args, err, NULL))
9283 return -1;
9284
Willy Tarreauef934602016-12-22 23:12:01 +01009285 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009286 return 0;
9287}
9288
9289/* parse "ssl.lifetime".
9290 * Returns <0 on alert, >0 on warning, 0 on success.
9291 */
9292static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9293 struct proxy *defpx, const char *file, int line,
9294 char **err)
9295{
9296 const char *res;
9297
9298 if (too_many_args(1, args, err, NULL))
9299 return -1;
9300
9301 if (*(args[1]) == 0) {
9302 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9303 return -1;
9304 }
9305
Willy Tarreauef934602016-12-22 23:12:01 +01009306 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009307 if (res == PARSE_TIME_OVER) {
9308 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9309 args[1], args[0]);
9310 return -1;
9311 }
9312 else if (res == PARSE_TIME_UNDER) {
9313 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9314 args[1], args[0]);
9315 return -1;
9316 }
9317 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009318 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9319 return -1;
9320 }
9321 return 0;
9322}
9323
9324#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009325/* parse "ssl-dh-param-file".
9326 * Returns <0 on alert, >0 on warning, 0 on success.
9327 */
9328static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9329 struct proxy *defpx, const char *file, int line,
9330 char **err)
9331{
9332 if (too_many_args(1, args, err, NULL))
9333 return -1;
9334
9335 if (*(args[1]) == 0) {
9336 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9337 return -1;
9338 }
9339
9340 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9341 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9342 return -1;
9343 }
9344 return 0;
9345}
9346
Willy Tarreau9ceda382016-12-21 23:13:03 +01009347/* parse "ssl.default-dh-param".
9348 * Returns <0 on alert, >0 on warning, 0 on success.
9349 */
9350static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9351 struct proxy *defpx, const char *file, int line,
9352 char **err)
9353{
9354 if (too_many_args(1, args, err, NULL))
9355 return -1;
9356
9357 if (*(args[1]) == 0) {
9358 memprintf(err, "'%s' expects an integer argument.", args[0]);
9359 return -1;
9360 }
9361
Willy Tarreauef934602016-12-22 23:12:01 +01009362 global_ssl.default_dh_param = atoi(args[1]);
9363 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009364 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9365 return -1;
9366 }
9367 return 0;
9368}
9369#endif
9370
9371
William Lallemand32af2032016-10-29 18:09:35 +02009372/* This function is used with TLS ticket keys management. It permits to browse
9373 * each reference. The variable <getnext> must contain the current node,
9374 * <end> point to the root node.
9375 */
9376#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9377static inline
9378struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9379{
9380 struct tls_keys_ref *ref = getnext;
9381
9382 while (1) {
9383
9384 /* Get next list entry. */
9385 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9386
9387 /* If the entry is the last of the list, return NULL. */
9388 if (&ref->list == end)
9389 return NULL;
9390
9391 return ref;
9392 }
9393}
9394
9395static inline
9396struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9397{
9398 int id;
9399 char *error;
9400
9401 /* If the reference starts by a '#', this is numeric id. */
9402 if (reference[0] == '#') {
9403 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9404 id = strtol(reference + 1, &error, 10);
9405 if (*error != '\0')
9406 return NULL;
9407
9408 /* Perform the unique id lookup. */
9409 return tlskeys_ref_lookupid(id);
9410 }
9411
9412 /* Perform the string lookup. */
9413 return tlskeys_ref_lookup(reference);
9414}
9415#endif
9416
9417
9418#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9419
9420static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9421
9422static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9423 return cli_io_handler_tlskeys_files(appctx);
9424}
9425
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009426/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9427 * (next index to be dumped), and cli.p0 (next key reference).
9428 */
William Lallemand32af2032016-10-29 18:09:35 +02009429static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9430
9431 struct stream_interface *si = appctx->owner;
9432
9433 switch (appctx->st2) {
9434 case STAT_ST_INIT:
9435 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009436 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009437 * later and restart at the state "STAT_ST_INIT".
9438 */
9439 chunk_reset(&trash);
9440
9441 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9442 chunk_appendf(&trash, "# id secret\n");
9443 else
9444 chunk_appendf(&trash, "# id (file)\n");
9445
Willy Tarreau06d80a92017-10-19 14:32:15 +02009446 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009447 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009448 return 0;
9449 }
9450
William Lallemand32af2032016-10-29 18:09:35 +02009451 /* Now, we start the browsing of the references lists.
9452 * Note that the following call to LIST_ELEM return bad pointer. The only
9453 * available field of this pointer is <list>. It is used with the function
9454 * tlskeys_list_get_next() for retruning the first available entry
9455 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009456 if (appctx->ctx.cli.p0 == NULL) {
9457 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9458 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009459 }
9460
9461 appctx->st2 = STAT_ST_LIST;
9462 /* fall through */
9463
9464 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009465 while (appctx->ctx.cli.p0) {
9466 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009467
9468 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009469 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009470 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009471
9472 if (appctx->ctx.cli.i1 == 0)
9473 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9474
William Lallemand32af2032016-10-29 18:09:35 +02009475 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009476 int head;
9477
9478 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9479 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009480 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009481 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009482
9483 chunk_reset(t2);
9484 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009485 if (ref->key_size_bits == 128) {
9486 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9487 sizeof(struct tls_sess_key_128),
9488 t2->area, t2->size);
9489 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9490 t2->area);
9491 }
9492 else if (ref->key_size_bits == 256) {
9493 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9494 sizeof(struct tls_sess_key_256),
9495 t2->area, t2->size);
9496 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9497 t2->area);
9498 }
9499 else {
9500 /* This case should never happen */
9501 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9502 }
William Lallemand32af2032016-10-29 18:09:35 +02009503
Willy Tarreau06d80a92017-10-19 14:32:15 +02009504 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009505 /* let's try again later from this stream. We add ourselves into
9506 * this stream's users so that it can remove us upon termination.
9507 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009508 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009509 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009510 return 0;
9511 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009512 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009513 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009514 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009515 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009516 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009517 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009518 /* let's try again later from this stream. We add ourselves into
9519 * this stream's users so that it can remove us upon termination.
9520 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009521 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009522 return 0;
9523 }
9524
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009525 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009526 break;
9527
9528 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009529 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009530 }
9531
9532 appctx->st2 = STAT_ST_FIN;
9533 /* fall through */
9534
9535 default:
9536 appctx->st2 = STAT_ST_FIN;
9537 return 1;
9538 }
9539 return 0;
9540}
9541
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009542/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009543static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009544{
William Lallemand32af2032016-10-29 18:09:35 +02009545 /* no parameter, shows only file list */
9546 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009547 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009548 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009549 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009550 }
9551
9552 if (args[2][0] == '*') {
9553 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009554 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009555 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009556 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009557 if (!appctx->ctx.cli.p0)
9558 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009559 }
William Lallemand32af2032016-10-29 18:09:35 +02009560 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009561 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009562}
9563
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009564static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009565{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009566 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009567 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009568
William Lallemand32af2032016-10-29 18:09:35 +02009569 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009570 if (!*args[3] || !*args[4])
9571 return cli_err(appctx, "'set ssl tls-key' expects a filename and the new TLS key in base64 encoding.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009572
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009573 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009574 if (!ref)
9575 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009576
Willy Tarreau1c913e42018-08-22 05:26:57 +02009577 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009578 if (ret < 0)
9579 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009580
Willy Tarreau1c913e42018-08-22 05:26:57 +02009581 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009582 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9583 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009584
Willy Tarreau9d008692019-08-09 11:21:01 +02009585 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009586}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009587#endif
William Lallemand32af2032016-10-29 18:09:35 +02009588
William Lallemand150bfa82019-09-19 17:12:49 +02009589static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
9590{
9591 struct ckch_store *ckchs = NULL;
9592 struct cert_key_and_chain *ckch;
9593 struct list tmp_ckchi_list;
9594 BIO *mem;
9595 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +02009596 int i;
William Lallemand150bfa82019-09-19 17:12:49 +02009597 int found = 0;
9598 int bundle = -1;
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009599 int errcode = 0;
William Lallemand150bfa82019-09-19 17:12:49 +02009600
9601 if (!*args[3] || !payload)
9602 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
9603
9604 /* The operations on the CKCH architecture are locked so we can
9605 * manipulate ckch_store and ckch_inst */
9606 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
9607 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
9608
9609 LIST_INIT(&tmp_ckchi_list);
9610
9611 mem = BIO_new_mem_buf(payload, -1);
9612 if (!mem) {
9613 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009614 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009615 goto end;
9616 }
9617
9618 /* do 2 iterations, first one with a non-bundle entry, second one with a bundle entry */
9619 for (i = 0; i < 2; i++) {
9620
9621 if ((ckchs = ckchs_lookup(args[3])) != NULL) {
9622 struct ckch_inst *ckchi, *ckchis;
9623
9624 /* only the bundle name is in the tree and you should never update a bundle name, only a filename */
9625 if (bundle < 0 && ckchs->multi) {
9626 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
9627 err ? err : "", args[3], args[3]);
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009628 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009629 goto end;
9630 }
9631
9632 if (bundle < 0)
9633 ckch = ckchs->ckch;
9634 else
9635 ckch = &ckchs->ckch[bundle];
9636
9637 if (ckchs->filters) {
9638 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
9639 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009640 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009641 goto end;
9642 }
9643
9644 found = 1;
9645
9646 if (ssl_sock_load_crt_file_into_ckch(args[3], mem, ckch, &err) != 0) {
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009647 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009648 goto end;
9649 }
9650
9651 /* walk through ckch_inst and creates new ckch_inst using the updated ckch */
9652 list_for_each_entry(ckchi, &ckchs->ckch_inst, by_ckchs) {
9653 struct ckch_inst *new_inst;
9654
9655 if (ckchs->multi)
Emeric Brun054563d2019-10-17 13:16:58 +02009656 errcode |= ckch_inst_new_load_multi_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand150bfa82019-09-19 17:12:49 +02009657 else
Emeric Brun054563d2019-10-17 13:16:58 +02009658 errcode |= ckch_inst_new_load_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &new_inst, &err);
William Lallemand150bfa82019-09-19 17:12:49 +02009659
Emeric Brun054563d2019-10-17 13:16:58 +02009660 if (errcode & ERR_CODE)
William Lallemand150bfa82019-09-19 17:12:49 +02009661 goto end;
William Lallemand150bfa82019-09-19 17:12:49 +02009662
9663 /* link temporary the new ckch_inst */
9664 LIST_ADDQ(&tmp_ckchi_list, &new_inst->by_ckchs);
9665 }
9666
9667 /* once every allocation is done, delete the old sni_ctx & the old ckch_insts */
9668 list_for_each_entry_safe(ckchi, ckchis, &ckchs->ckch_inst, by_ckchs) {
9669 struct sni_ctx *sc0, *sc0s;
9670
9671 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9672 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9673 ebmb_delete(&sc0->name);
9674 LIST_DEL(&sc0->by_ckch_inst);
9675 free(sc0);
9676 }
9677 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9678 LIST_DEL(&ckchi->by_ckchs);
9679 free(ckchi);
9680 ckchi = NULL;
9681 }
9682 /* insert every new ckch instance in the actual list and insert the sni_ctx in the trees */
9683 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9684 LIST_DEL(&ckchi->by_ckchs);
9685 LIST_ADD(&ckchs->ckch_inst, &ckchi->by_ckchs);
9686 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9687 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
9688 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9689 }
9690 }
William Lallemand963b2e72019-10-14 11:38:36 +02009691#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
9692 {
9693 char *end = NULL;
9694 int j;
William Lallemand150bfa82019-09-19 17:12:49 +02009695
William Lallemand963b2e72019-10-14 11:38:36 +02009696 /* check if it was also used as a bundle by removing the
9697 * .dsa/.rsa/.ecdsa at the end of the filename */
9698 if (bundle >= 0)
William Lallemand150bfa82019-09-19 17:12:49 +02009699 break;
William Lallemand963b2e72019-10-14 11:38:36 +02009700 end = strrchr(args[3], '.');
9701 for (j = 0; *end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
9702 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
9703 bundle = j; /* keep the type of certificate so we insert it at the right place */
9704 *end = '\0'; /* it's a bundle let's end the string*/
9705 break;
9706 }
William Lallemand150bfa82019-09-19 17:12:49 +02009707 }
9708 }
William Lallemand963b2e72019-10-14 11:38:36 +02009709#else
9710 /* bundles are not supported here, so we don't need to lookup again */
9711 break;
9712#endif
William Lallemand150bfa82019-09-19 17:12:49 +02009713 }
9714
9715 if (!found) {
William Lallemand150bfa82019-09-19 17:12:49 +02009716 memprintf(&err, "%sCan't replace a certificate name which is not referenced by the configuration!\n",
9717 err ? err : "");
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009718 errcode |= ERR_ALERT | ERR_FATAL;
William Lallemand150bfa82019-09-19 17:12:49 +02009719 }
9720
9721end:
9722
9723 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
9724
9725 BIO_free(mem);
9726
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009727 if (errcode & ERR_CODE) {
William Lallemand150bfa82019-09-19 17:12:49 +02009728 struct ckch_inst *ckchi, *ckchis;
9729 /* if the allocation failed, we need to free everything from the temporary list */
9730 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9731 struct sni_ctx *sc0, *sc0s;
9732
9733 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9734 if (sc0->order == 0) /* we only free if it's the first inserted */
9735 SSL_CTX_free(sc0->ctx);
9736 LIST_DEL(&sc0->by_ckch_inst);
9737 free(sc0);
9738 }
9739 LIST_DEL(&ckchi->by_ckchs);
9740 free(ckchi);
9741 }
9742 return cli_dynerr(appctx, memprintf(&err, "%sCan't update the certificate!\n", err ? err : ""));
Emeric Brunf69ed1d2019-10-17 11:56:56 +02009743 }
9744 else if (errcode & ERR_WARN) {
9745 return cli_dynmsg(appctx, LOG_WARNING, memprintf(&err, "%sCertificate updated!\n", err ? err : ""));
9746 }
9747 else {
William Lallemand150bfa82019-09-19 17:12:49 +02009748 return cli_dynmsg(appctx, LOG_INFO, memprintf(&err, "Certificate updated!"));
9749 }
9750}
9751
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009752static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009753{
9754#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9755 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009756 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009757
9758 if (!payload)
9759 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009760
9761 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009762 if (!*payload)
9763 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009764
9765 /* remove \r and \n from the payload */
9766 for (i = 0, j = 0; payload[i]; i++) {
9767 if (payload[i] == '\r' || payload[i] == '\n')
9768 continue;
9769 payload[j++] = payload[i];
9770 }
9771 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009772
Willy Tarreau1c913e42018-08-22 05:26:57 +02009773 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009774 if (ret < 0)
9775 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009776
Willy Tarreau1c913e42018-08-22 05:26:57 +02009777 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009778 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +02009779 if (err)
9780 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
9781 else
9782 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009783 }
Willy Tarreau9d008692019-08-09 11:21:01 +02009784
9785 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009786#else
Willy Tarreau9d008692019-08-09 11:21:01 +02009787 return cli_err(appctx, "HAProxy was compiled against a version of OpenSSL that doesn't support OCSP stapling.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009788#endif
9789
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009790}
9791
Willy Tarreau86a394e2019-05-09 14:15:32 +02009792#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009793static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9794{
9795 switch (arg->type) {
9796 case ARGT_STR:
9797 smp->data.type = SMP_T_STR;
9798 smp->data.u.str = arg->data.str;
9799 return 1;
9800 case ARGT_VAR:
9801 if (!vars_get_by_desc(&arg->data.var, smp))
9802 return 0;
9803 if (!sample_casts[smp->data.type][SMP_T_STR])
9804 return 0;
9805 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9806 return 0;
9807 return 1;
9808 default:
9809 return 0;
9810 }
9811}
9812
9813static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9814 const char *file, int line, char **err)
9815{
9816 switch(args[0].data.sint) {
9817 case 128:
9818 case 192:
9819 case 256:
9820 break;
9821 default:
9822 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9823 return 0;
9824 }
9825 /* Try to decode a variable. */
9826 vars_check_arg(&args[1], NULL);
9827 vars_check_arg(&args[2], NULL);
9828 vars_check_arg(&args[3], NULL);
9829 return 1;
9830}
9831
9832/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9833static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9834{
9835 struct sample nonce, key, aead_tag;
9836 struct buffer *smp_trash, *smp_trash_alloc;
9837 EVP_CIPHER_CTX *ctx;
9838 int dec_size, ret;
9839
9840 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9841 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9842 return 0;
9843
9844 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9845 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9846 return 0;
9847
9848 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9849 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9850 return 0;
9851
9852 smp_trash = get_trash_chunk();
9853 smp_trash_alloc = alloc_trash_chunk();
9854 if (!smp_trash_alloc)
9855 return 0;
9856
9857 ctx = EVP_CIPHER_CTX_new();
9858
9859 if (!ctx)
9860 goto err;
9861
9862 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9863 if (dec_size < 0)
9864 goto err;
9865 smp_trash->data = dec_size;
9866
9867 /* Set cipher type and mode */
9868 switch(arg_p[0].data.sint) {
9869 case 128:
9870 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9871 break;
9872 case 192:
9873 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9874 break;
9875 case 256:
9876 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9877 break;
9878 }
9879
9880 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9881
9882 /* Initialise IV */
9883 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9884 goto err;
9885
9886 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9887 if (dec_size < 0)
9888 goto err;
9889 smp_trash->data = dec_size;
9890
9891 /* Initialise key */
9892 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9893 goto err;
9894
9895 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9896 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9897 goto err;
9898
9899 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9900 if (dec_size < 0)
9901 goto err;
9902 smp_trash_alloc->data = dec_size;
9903 dec_size = smp_trash->data;
9904
9905 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9906 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9907
9908 if (ret <= 0)
9909 goto err;
9910
9911 smp->data.u.str.data = dec_size + smp_trash->data;
9912 smp->data.u.str.area = smp_trash->area;
9913 smp->data.type = SMP_T_BIN;
9914 smp->flags &= ~SMP_F_CONST;
9915 free_trash_chunk(smp_trash_alloc);
9916 return 1;
9917
9918err:
9919 free_trash_chunk(smp_trash_alloc);
9920 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009921}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009922# endif
William Lallemand32af2032016-10-29 18:09:35 +02009923
9924/* register cli keywords */
9925static struct cli_kw_list cli_kws = {{ },{
9926#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9927 { { "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 +02009928 { { "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 +02009929#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009930 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand150bfa82019-09-19 17:12:49 +02009931 { { "set", "ssl", "cert", NULL }, "set ssl cert <certfile> <payload> : replace a certificate file", cli_parse_set_cert, NULL },
William Lallemand32af2032016-10-29 18:09:35 +02009932 { { NULL }, NULL, NULL, NULL }
9933}};
9934
Willy Tarreau0108d902018-11-25 19:14:37 +01009935INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009936
Willy Tarreau7875d092012-09-10 08:20:03 +02009937/* Note: must not be declared <const> as its list will be overwritten.
9938 * Please take care of keeping this list alphabetically sorted.
9939 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009940static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009941 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009942 { "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 +01009943#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009944 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009945#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009946 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009947#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9948 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9949#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009950 { "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 +02009951 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009952 { "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 +02009953 { "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 +02009954#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009955 { "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 -04009956#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009957#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009958 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9959 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -04009960 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9961#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009962 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9963 { "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 +01009964 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009965 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009966 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9967 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9968 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9969 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9970 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9971 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9972 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9973 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009974 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009975 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9976 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009977 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009978 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9979 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9980 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9981 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9982 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9983 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9984 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009985 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009986 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009987 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009988 { "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 +01009989 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009990 { "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 +02009991 { "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 +01009992 { "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 +02009993 { "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 +01009994#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009995 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009996#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009997#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009998 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009999#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010000 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010001#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +020010002 { "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 -040010003#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +020010004 { "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 +020010005#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010006 { "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 -040010007#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010008#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -040010009 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10010 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -040010011 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10012#endif
Patrick Hemmer41966772018-04-28 19:15:48 -040010013#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +010010014 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -040010015#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010016 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10017 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
10018 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
10019 { "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 +020010020 { NULL, NULL, 0, 0, 0 },
10021}};
10022
Willy Tarreau0108d902018-11-25 19:14:37 +010010023INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
10024
Willy Tarreau7875d092012-09-10 08:20:03 +020010025/* Note: must not be declared <const> as its list will be overwritten.
10026 * Please take care of keeping this list alphabetically sorted.
10027 */
Willy Tarreaudc13c112013-06-21 23:16:39 +020010028static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010029 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10030 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010031 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010032}};
10033
Willy Tarreau0108d902018-11-25 19:14:37 +010010034INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10035
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010036/* Note: must not be declared <const> as its list will be overwritten.
10037 * Please take care of keeping this list alphabetically sorted, doing so helps
10038 * all code contributors.
10039 * Optional keywords are also declared with a NULL ->parse() function so that
10040 * the config parser can report an appropriate error when a known keyword was
10041 * not enabled.
10042 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010043static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010044 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010045 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10046 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10047 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010048#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010049 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10050#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010051 { "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 +010010052 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010053 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010054 { "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 +010010055 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010056 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10057 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010058 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10059 { NULL, NULL, 0 },
10060};
10061
Willy Tarreau0108d902018-11-25 19:14:37 +010010062/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10063
Willy Tarreau51fb7652012-09-18 18:24:39 +020010064static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010065 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010066 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10067 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10068 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10069 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10070 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10071 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010072#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010073 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10074#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010075 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10076 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10077 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10078 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10079 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10080 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10081 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10082 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10083 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10084 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010085 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010086 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010087 { "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 +020010088 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10089 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10090 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10091 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010092 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010093 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10094 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010095 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10096 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010097 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10098 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10099 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10100 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10101 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010102 { NULL, NULL, 0 },
10103}};
Emeric Brun46591952012-05-18 15:47:34 +020010104
Willy Tarreau0108d902018-11-25 19:14:37 +010010105INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10106
Willy Tarreau92faadf2012-10-10 23:04:25 +020010107/* Note: must not be declared <const> as its list will be overwritten.
10108 * Please take care of keeping this list alphabetically sorted, doing so helps
10109 * all code contributors.
10110 * Optional keywords are also declared with a NULL ->parse() function so that
10111 * the config parser can report an appropriate error when a known keyword was
10112 * not enabled.
10113 */
10114static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010115 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010116 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010117 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010118 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010119 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010120 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10121 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010122#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010123 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10124#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010125 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10126 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10127 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10128 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10129 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10130 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10131 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10132 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10133 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10134 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10135 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10136 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10137 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10138 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10139 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10140 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10141 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10142 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010143 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010144 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10145 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10146 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10147 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10148 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10149 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10150 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10151 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10152 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10153 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010154 { NULL, NULL, 0, 0 },
10155}};
10156
Willy Tarreau0108d902018-11-25 19:14:37 +010010157INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10158
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010159static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010160 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10161 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010162 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010163 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10164 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010165#ifndef OPENSSL_NO_DH
10166 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10167#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010168 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010169#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010170 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010171#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010172 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10173#ifndef OPENSSL_NO_DH
10174 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10175#endif
10176 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10177 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10178 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10179 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010180 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010181 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10182 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010183#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010184 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10185 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10186#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010187 { 0, NULL, NULL },
10188}};
10189
Willy Tarreau0108d902018-11-25 19:14:37 +010010190INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10191
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010192/* Note: must not be declared <const> as its list will be overwritten */
10193static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010194#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010195 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10196#endif
10197 { NULL, NULL, 0, 0, 0 },
10198}};
10199
10200INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10201
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010202/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010203static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010204 .snd_buf = ssl_sock_from_buf,
10205 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010206 .subscribe = ssl_subscribe,
10207 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010208 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010209 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010210 .rcv_pipe = NULL,
10211 .snd_pipe = NULL,
10212 .shutr = NULL,
10213 .shutw = ssl_sock_shutw,
10214 .close = ssl_sock_close,
10215 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010216 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010217 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010218 .prepare_srv = ssl_sock_prepare_srv_ctx,
10219 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010220 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010221 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010222};
10223
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010224enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10225 struct session *sess, struct stream *s, int flags)
10226{
10227 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010228 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010229
10230 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010231 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010232
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010233 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010234 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010235 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010236 s->req.flags |= CF_READ_NULL;
10237 return ACT_RET_YIELD;
10238 }
10239 }
10240 return (ACT_RET_CONT);
10241}
10242
10243static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10244{
10245 rule->action_ptr = ssl_action_wait_for_hs;
10246
10247 return ACT_RET_PRS_OK;
10248}
10249
10250static struct action_kw_list http_req_actions = {ILH, {
10251 { "wait-for-handshake", ssl_parse_wait_for_hs },
10252 { /* END */ }
10253}};
10254
Willy Tarreau0108d902018-11-25 19:14:37 +010010255INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10256
Willy Tarreau5db847a2019-05-09 14:13:35 +020010257#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010258
10259static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10260{
10261 if (ptr) {
10262 chunk_destroy(ptr);
10263 free(ptr);
10264 }
10265}
10266
10267#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010268static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10269{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010270 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010271}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010272
Emeric Brun46591952012-05-18 15:47:34 +020010273__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010274static void __ssl_sock_init(void)
10275{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010276#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010277 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010278 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010279#endif
Emeric Brun46591952012-05-18 15:47:34 +020010280
Willy Tarreauef934602016-12-22 23:12:01 +010010281 if (global_ssl.listen_default_ciphers)
10282 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10283 if (global_ssl.connect_default_ciphers)
10284 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010285#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010286 if (global_ssl.listen_default_ciphersuites)
10287 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10288 if (global_ssl.connect_default_ciphersuites)
10289 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10290#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010291
Willy Tarreau13e14102016-12-22 20:25:26 +010010292 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010293#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010294 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010295#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010296#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010297 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010298 n = sk_SSL_COMP_num(cm);
10299 while (n--) {
10300 (void) sk_SSL_COMP_pop(cm);
10301 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010302#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010303
Willy Tarreau5db847a2019-05-09 14:13:35 +020010304#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010305 ssl_locking_init();
10306#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010307#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010308 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10309#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010310 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010311 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 +010010312 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010313#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010314 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010315 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010316#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010317#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10318 hap_register_post_check(tlskeys_finalize_config);
10319#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010320
10321 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10322 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10323
10324#ifndef OPENSSL_NO_DH
10325 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10326 hap_register_post_deinit(ssl_free_dh);
10327#endif
10328#ifndef OPENSSL_NO_ENGINE
10329 hap_register_post_deinit(ssl_free_engines);
10330#endif
10331 /* Load SSL string for the verbose & debug mode. */
10332 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010333 ha_meth = BIO_meth_new(0x666, "ha methods");
10334 BIO_meth_set_write(ha_meth, ha_ssl_write);
10335 BIO_meth_set_read(ha_meth, ha_ssl_read);
10336 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10337 BIO_meth_set_create(ha_meth, ha_ssl_new);
10338 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10339 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10340 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020010341
10342 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010010343}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010344
Willy Tarreau80713382018-11-26 10:19:54 +010010345/* Compute and register the version string */
10346static void ssl_register_build_options()
10347{
10348 char *ptr = NULL;
10349 int i;
10350
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010351 memprintf(&ptr, "Built with OpenSSL version : "
10352#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010353 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010354#else /* OPENSSL_IS_BORINGSSL */
10355 OPENSSL_VERSION_TEXT
10356 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010357 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010358 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010359#endif
10360 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010361#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010362 "no (library version too old)"
10363#elif defined(OPENSSL_NO_TLSEXT)
10364 "no (disabled via OPENSSL_NO_TLSEXT)"
10365#else
10366 "yes"
10367#endif
10368 "", ptr);
10369
10370 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10371#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10372 "yes"
10373#else
10374#ifdef OPENSSL_NO_TLSEXT
10375 "no (because of OPENSSL_NO_TLSEXT)"
10376#else
10377 "no (version might be too old, 0.9.8f min needed)"
10378#endif
10379#endif
10380 "", ptr);
10381
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010382 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10383 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10384 if (methodVersions[i].option)
10385 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010386
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010387 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010388}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010389
Willy Tarreau80713382018-11-26 10:19:54 +010010390INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010391
Emeric Brun46591952012-05-18 15:47:34 +020010392
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010393#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010394void ssl_free_engines(void) {
10395 struct ssl_engine_list *wl, *wlb;
10396 /* free up engine list */
10397 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10398 ENGINE_finish(wl->e);
10399 ENGINE_free(wl->e);
10400 LIST_DEL(&wl->list);
10401 free(wl);
10402 }
10403}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010404#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010405
Remi Gacogned3a23c32015-05-28 16:39:47 +020010406#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010407void ssl_free_dh(void) {
10408 if (local_dh_1024) {
10409 DH_free(local_dh_1024);
10410 local_dh_1024 = NULL;
10411 }
10412 if (local_dh_2048) {
10413 DH_free(local_dh_2048);
10414 local_dh_2048 = NULL;
10415 }
10416 if (local_dh_4096) {
10417 DH_free(local_dh_4096);
10418 local_dh_4096 = NULL;
10419 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010420 if (global_dh) {
10421 DH_free(global_dh);
10422 global_dh = NULL;
10423 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010424}
10425#endif
10426
10427__attribute__((destructor))
10428static void __ssl_sock_deinit(void)
10429{
10430#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010431 if (ssl_ctx_lru_tree) {
10432 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010433 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010434 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010435#endif
10436
Willy Tarreau5db847a2019-05-09 14:13:35 +020010437#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010438 ERR_remove_state(0);
10439 ERR_free_strings();
10440
10441 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010442#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010443
Willy Tarreau5db847a2019-05-09 14:13:35 +020010444#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010445 CRYPTO_cleanup_all_ex_data();
10446#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010447 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010448}
10449
10450
Emeric Brun46591952012-05-18 15:47:34 +020010451/*
10452 * Local variables:
10453 * c-indent-level: 8
10454 * c-basic-offset: 8
10455 * End:
10456 */