blob: 1143065eca5353950961b031112558da4d593025 [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
3056 * Currently, this does not process any information about ocsp, dhparams or
3057 * sctl
3058 * Returns
3059 * 0 on success
3060 * 1 on failure
3061 */
3062static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_and_chain *ckch, SSL_CTX *ctx, char **err)
3063{
yanbzhu488a4d22015-12-01 15:16:07 -05003064 if (SSL_CTX_use_PrivateKey(ctx, ckch->key) <= 0) {
3065 memprintf(err, "%sunable to load SSL private key into SSL Context '%s'.\n",
3066 err && *err ? *err : "", path);
3067 return 1;
3068 }
3069
3070 if (!SSL_CTX_use_certificate(ctx, ckch->cert)) {
3071 memprintf(err, "%sunable to load SSL certificate into SSL Context '%s'.\n",
3072 err && *err ? *err : "", path);
3073 return 1;
3074 }
3075
yanbzhu488a4d22015-12-01 15:16:07 -05003076 /* Load all certs in the ckch into the ctx_chain for the ssl_ctx */
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003077#ifdef SSL_CTX_set1_chain
Emmanuel Hocdet9246f8b2018-11-30 16:00:21 +01003078 if (!SSL_CTX_set1_chain(ctx, ckch->chain)) {
3079 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'. Make sure you are linking against Openssl >= 1.0.2.\n",
3080 err && *err ? *err : "", path);
3081 return 1;
yanbzhu488a4d22015-12-01 15:16:07 -05003082 }
Emmanuel Hocdet1c65fdd2018-12-03 18:07:44 +01003083#else
3084 { /* legacy compat (< openssl 1.0.2) */
3085 X509 *ca;
3086 while ((ca = sk_X509_shift(ckch->chain)))
3087 if (!SSL_CTX_add_extra_chain_cert(ctx, ca)) {
3088 memprintf(err, "%sunable to load chain certificate into SSL Context '%s'.\n",
3089 err && *err ? *err : "", path);
3090 X509_free(ca);
3091 return 1;
3092 }
3093 }
3094#endif
yanbzhu488a4d22015-12-01 15:16:07 -05003095
William Lallemandfa892222019-07-23 16:06:08 +02003096#ifndef OPENSSL_NO_DH
3097 /* store a NULL pointer to indicate we have not yet loaded
3098 a custom DH param file */
3099 if (ssl_dh_ptr_index >= 0) {
3100 SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
3101 }
3102
3103 if (ssl_sock_load_dh_params(ctx, ckch) < 0) {
3104 memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
3105 err && *err ? *err : "", path);
3106 return 1;
3107 }
3108#endif
3109
William Lallemanda17f4112019-10-10 15:16:44 +02003110#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
3111 if (sctl_ex_index >= 0 && ckch->sctl) {
3112 if (ssl_sock_load_sctl(ctx, ckch->sctl) < 0) {
3113 memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
3114 *err ? *err : "", path);
3115 return 1;
3116 }
3117 }
3118#endif
3119
William Lallemand4a660132019-10-14 14:51:41 +02003120#if ((defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP) || defined OPENSSL_IS_BORINGSSL)
William Lallemand246c0242019-10-11 08:59:13 +02003121 /* Load OCSP Info into context */
3122 if (ckch->ocsp_response) {
3123 if (ssl_sock_load_ocsp(ctx, ckch) < 0) {
3124 if (err)
3125 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",
3126 *err ? *err : "", path);
3127 return 1;
3128 }
3129 }
William Lallemand246c0242019-10-11 08:59:13 +02003130#endif
3131
yanbzhu488a4d22015-12-01 15:16:07 -05003132 return 0;
3133}
3134
William Lallemandc4ecddf2019-07-31 16:50:08 +02003135#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu08ce6ab2015-12-02 13:01:29 -05003136
William Lallemand28a8fce2019-10-04 17:36:55 +02003137static int ssl_sock_populate_sni_keytypes_hplr(const char *str, struct eb_root *sni_keytypes, int key_index)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003138{
3139 struct sni_keytype *s_kt = NULL;
3140 struct ebmb_node *node;
3141 int i;
3142
3143 for (i = 0; i < trash.size; i++) {
3144 if (!str[i])
3145 break;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003146 trash.area[i] = tolower(str[i]);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003147 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003148 trash.area[i] = 0;
3149 node = ebst_lookup(sni_keytypes, trash.area);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003150 if (!node) {
3151 /* CN not found in tree */
3152 s_kt = malloc(sizeof(struct sni_keytype) + i + 1);
3153 /* Using memcpy here instead of strncpy.
3154 * strncpy will cause sig_abrt errors under certain versions of gcc with -O2
3155 * See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60792
3156 */
William Lallemand28a8fce2019-10-04 17:36:55 +02003157 if (!s_kt)
3158 return -1;
3159
Willy Tarreau843b7cb2018-07-13 10:54:26 +02003160 memcpy(s_kt->name.key, trash.area, i+1);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003161 s_kt->keytypes = 0;
3162 ebst_insert(sni_keytypes, &s_kt->name);
3163 } else {
3164 /* CN found in tree */
3165 s_kt = container_of(node, struct sni_keytype, name);
3166 }
3167
3168 /* Mark that this CN has the keytype of key_index via keytypes mask */
3169 s_kt->keytypes |= 1<<key_index;
3170
William Lallemand28a8fce2019-10-04 17:36:55 +02003171 return 0;
3172
yanbzhu08ce6ab2015-12-02 13:01:29 -05003173}
3174
William Lallemandc4ecddf2019-07-31 16:50:08 +02003175#endif
3176
William Lallemand36b84632019-07-18 19:28:17 +02003177/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003178 * lookup a path into the ckchs tree.
William Lallemand6af03992019-07-23 15:00:54 +02003179 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003180static inline struct ckch_store *ckchs_lookup(char *path)
William Lallemand6af03992019-07-23 15:00:54 +02003181{
3182 struct ebmb_node *eb;
3183
William Lallemande3af8fb2019-10-08 11:36:53 +02003184 eb = ebst_lookup(&ckchs_tree, path);
William Lallemand6af03992019-07-23 15:00:54 +02003185 if (!eb)
3186 return NULL;
3187
William Lallemande3af8fb2019-10-08 11:36:53 +02003188 return ebmb_entry(eb, struct ckch_store, node);
William Lallemand6af03992019-07-23 15:00:54 +02003189}
3190
3191/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003192 * This function allocate a ckch_store and populate it with certificates from files.
William Lallemand36b84632019-07-18 19:28:17 +02003193 */
William Lallemande3af8fb2019-10-08 11:36:53 +02003194static struct ckch_store *ckchs_load_cert_file(char *path, int multi, char **err)
William Lallemand36b84632019-07-18 19:28:17 +02003195{
William Lallemande3af8fb2019-10-08 11:36:53 +02003196 struct ckch_store *ckchs;
William Lallemand36b84632019-07-18 19:28:17 +02003197
William Lallemande3af8fb2019-10-08 11:36:53 +02003198 ckchs = calloc(1, sizeof(*ckchs) + strlen(path) + 1);
3199 if (!ckchs) {
William Lallemand36b84632019-07-18 19:28:17 +02003200 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3201 goto end;
3202 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003203 ckchs->ckch = calloc(1, sizeof(*ckchs->ckch) * (multi ? SSL_SOCK_NUM_KEYTYPES : 1));
William Lallemand36b84632019-07-18 19:28:17 +02003204
William Lallemande3af8fb2019-10-08 11:36:53 +02003205 if (!ckchs->ckch) {
William Lallemand36b84632019-07-18 19:28:17 +02003206 memprintf(err, "%sunable to allocate memory.\n", err && *err ? *err : "");
3207 goto end;
3208 }
3209
William Lallemand9117de92019-10-04 00:29:42 +02003210 LIST_INIT(&ckchs->ckch_inst);
3211
William Lallemand36b84632019-07-18 19:28:17 +02003212 if (!multi) {
3213
William Lallemandf11365b2019-09-19 14:25:58 +02003214 if (ssl_sock_load_crt_file_into_ckch(path, NULL, ckchs->ckch, err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003215 goto end;
3216
William Lallemande3af8fb2019-10-08 11:36:53 +02003217 /* insert into the ckchs tree */
3218 memcpy(ckchs->path, path, strlen(path) + 1);
3219 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003220 } else {
3221 int found = 0;
William Lallemandc4ecddf2019-07-31 16:50:08 +02003222#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3223 char fp[MAXPATHLEN+1] = {0};
3224 int n = 0;
William Lallemand36b84632019-07-18 19:28:17 +02003225
3226 /* Load all possible certs and keys */
3227 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3228 struct stat buf;
3229 snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3230 if (stat(fp, &buf) == 0) {
William Lallemandf11365b2019-09-19 14:25:58 +02003231 if (ssl_sock_load_crt_file_into_ckch(fp, NULL, &ckchs->ckch[n], err) == 1)
William Lallemand36b84632019-07-18 19:28:17 +02003232 goto end;
3233 found = 1;
William Lallemande3af8fb2019-10-08 11:36:53 +02003234 ckchs->multi = 1;
William Lallemand36b84632019-07-18 19:28:17 +02003235 }
3236 }
William Lallemandc4ecddf2019-07-31 16:50:08 +02003237#endif
William Lallemand36b84632019-07-18 19:28:17 +02003238
3239 if (!found) {
William Lallemand6e5f2ce2019-08-01 14:43:20 +02003240 memprintf(err, "%sDidn't find any certificate for bundle '%s'.\n", err && *err ? *err : "", path);
William Lallemand36b84632019-07-18 19:28:17 +02003241 goto end;
3242 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003243 /* insert into the ckchs tree */
3244 memcpy(ckchs->path, path, strlen(path) + 1);
3245 ebst_insert(&ckchs_tree, &ckchs->node);
William Lallemand36b84632019-07-18 19:28:17 +02003246 }
William Lallemande3af8fb2019-10-08 11:36:53 +02003247 return ckchs;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003248
William Lallemand36b84632019-07-18 19:28:17 +02003249end:
William Lallemande3af8fb2019-10-08 11:36:53 +02003250 if (ckchs) {
3251 free(ckchs->ckch);
3252 ebmb_delete(&ckchs->node);
William Lallemand6af03992019-07-23 15:00:54 +02003253 }
3254
William Lallemande3af8fb2019-10-08 11:36:53 +02003255 free(ckchs);
William Lallemand36b84632019-07-18 19:28:17 +02003256
3257 return NULL;
3258}
3259
William Lallemandc4ecddf2019-07-31 16:50:08 +02003260#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
3261
William Lallemand36b84632019-07-18 19:28:17 +02003262/*
William Lallemande3af8fb2019-10-08 11:36:53 +02003263 * Take a ckch_store which contains a multi-certificate bundle.
William Lallemand36b84632019-07-18 19:28:17 +02003264 * Group these certificates into a set of SSL_CTX*
yanbzhu08ce6ab2015-12-02 13:01:29 -05003265 * based on shared and unique CN and SAN entries. Add these SSL_CTX* to the SNI tree.
3266 *
Joseph Herlant017b3da2018-11-15 09:07:59 -08003267 * This will allow the user to explicitly group multiple cert/keys for a single purpose
yanbzhu08ce6ab2015-12-02 13:01:29 -05003268 *
3269 * Returns
3270 * 0 on success
3271 * 1 on failure
William Lallemand36b84632019-07-18 19:28:17 +02003272 *
3273 * TODO: This function shouldn't access files anymore, sctl and ocsp file access
3274 * should be migrated to the ssl_sock_load_crt_file_into_ckch() function
yanbzhu08ce6ab2015-12-02 13:01:29 -05003275 */
William Lallemand614ca0d2019-10-07 13:52:11 +02003276static struct ckch_inst *ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
William Lallemand36b84632019-07-18 19:28:17 +02003277 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3278 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003279{
William Lallemand36b84632019-07-18 19:28:17 +02003280 int i = 0, n = 0;
3281 struct cert_key_and_chain *certs_and_keys;
William Lallemand4b989f22019-10-04 18:36:55 +02003282 struct eb_root sni_keytypes_map = EB_ROOT;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003283 struct ebmb_node *node;
3284 struct ebmb_node *next;
3285 /* Array of SSL_CTX pointers corresponding to each possible combo
3286 * of keytypes
3287 */
3288 struct key_combo_ctx key_combos[SSL_SOCK_POSSIBLE_KT_COMBOS] = { {0} };
3289 int rv = 0;
3290 X509_NAME *xname = NULL;
3291 char *str = NULL;
3292#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3293 STACK_OF(GENERAL_NAME) *names = NULL;
3294#endif
William Lallemand614ca0d2019-10-07 13:52:11 +02003295 struct ckch_inst *ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003296
William Lallemande3af8fb2019-10-08 11:36:53 +02003297 if (!ckchs || !ckchs->ckch || !ckchs->multi) {
William Lallemand36b84632019-07-18 19:28:17 +02003298 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3299 err && *err ? *err : "", path);
William Lallemand614ca0d2019-10-07 13:52:11 +02003300 return NULL;
3301 }
3302
3303 ckch_inst = ckch_inst_new();
3304 if (!ckch_inst) {
3305 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3306 err && *err ? *err : "", path);
3307 goto end;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003308 }
3309
William Lallemande3af8fb2019-10-08 11:36:53 +02003310 certs_and_keys = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003311
William Lallemand150bfa82019-09-19 17:12:49 +02003312 /* at least one of the instances is using filters during the config
3313 * parsing, that's ok to inherit this during loading on CLI */
3314 ckchs->filters = !!fcount;
3315
yanbzhu08ce6ab2015-12-02 13:01:29 -05003316 /* Process each ckch and update keytypes for each CN/SAN
3317 * for example, if CN/SAN www.a.com is associated with
3318 * certs with keytype 0 and 2, then at the end of the loop,
3319 * www.a.com will have:
3320 * keyindex = 0 | 1 | 4 = 5
3321 */
3322 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003323 int ret;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003324
3325 if (!ssl_sock_is_ckch_valid(&certs_and_keys[n]))
3326 continue;
3327
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003328 if (fcount) {
William Lallemand28a8fce2019-10-04 17:36:55 +02003329 for (i = 0; i < fcount; i++) {
3330 ret = ssl_sock_populate_sni_keytypes_hplr(sni_filter[i], &sni_keytypes_map, n);
3331 if (ret < 0) {
3332 memprintf(err, "%sunable to allocate SSL context.\n",
3333 err && *err ? *err : "");
3334 rv = 1;
3335 goto end;
3336 }
3337 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003338 } else {
3339 /* A lot of the following code is OpenSSL boilerplate for processing CN's and SAN's,
3340 * so the line that contains logic is marked via comments
3341 */
3342 xname = X509_get_subject_name(certs_and_keys[n].cert);
3343 i = -1;
3344 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3345 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003346 ASN1_STRING *value;
3347 value = X509_NAME_ENTRY_get_data(entry);
3348 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003349 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003350 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003351
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003352 OPENSSL_free(str);
3353 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003354 if (ret < 0) {
3355 memprintf(err, "%sunable to allocate SSL context.\n",
3356 err && *err ? *err : "");
3357 rv = 1;
3358 goto end;
3359 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003360 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003361 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003362
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003363 /* Do the above logic for each SAN */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003364#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003365 names = X509_get_ext_d2i(certs_and_keys[n].cert, NID_subject_alt_name, NULL, NULL);
3366 if (names) {
3367 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3368 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003369
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003370 if (name->type == GEN_DNS) {
3371 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
3372 /* Important line is here */
William Lallemand28a8fce2019-10-04 17:36:55 +02003373 ret = ssl_sock_populate_sni_keytypes_hplr(str, &sni_keytypes_map, n);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003374
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003375 OPENSSL_free(str);
3376 str = NULL;
William Lallemand28a8fce2019-10-04 17:36:55 +02003377 if (ret < 0) {
3378 memprintf(err, "%sunable to allocate SSL context.\n",
3379 err && *err ? *err : "");
3380 rv = 1;
3381 goto end;
3382 }
Emmanuel Hocdetd294aea2016-05-13 11:14:06 +02003383 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003384 }
3385 }
3386 }
3387 }
3388#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
3389 }
3390
3391 /* If no files found, return error */
3392 if (eb_is_empty(&sni_keytypes_map)) {
3393 memprintf(err, "%sunable to load SSL certificate file '%s' file does not exist.\n",
3394 err && *err ? *err : "", path);
3395 rv = 1;
3396 goto end;
3397 }
3398
3399 /* We now have a map of CN/SAN to keytypes that are loaded in
3400 * Iterate through the map to create the SSL_CTX's (if needed)
3401 * and add each CTX to the SNI tree
3402 *
3403 * Some math here:
Joseph Herlant017b3da2018-11-15 09:07:59 -08003404 * There are 2^n - 1 possible combinations, each unique
yanbzhu08ce6ab2015-12-02 13:01:29 -05003405 * combination is denoted by the key in the map. Each key
3406 * has a value between 1 and 2^n - 1. Conveniently, the array
3407 * of SSL_CTX* is sized 2^n. So, we can simply use the i'th
3408 * entry in the array to correspond to the unique combo (key)
3409 * associated with i. This unique key combo (i) will be associated
3410 * with combos[i-1]
3411 */
3412
3413 node = ebmb_first(&sni_keytypes_map);
3414 while (node) {
3415 SSL_CTX *cur_ctx;
Bertrand Jacquin33423092016-11-13 16:37:13 +00003416 char cur_file[MAXPATHLEN+1];
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003417 const struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
yanbzhu08ce6ab2015-12-02 13:01:29 -05003418
3419 str = (char *)container_of(node, struct sni_keytype, name)->name.key;
3420 i = container_of(node, struct sni_keytype, name)->keytypes;
3421 cur_ctx = key_combos[i-1].ctx;
3422
3423 if (cur_ctx == NULL) {
3424 /* need to create SSL_CTX */
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01003425 cur_ctx = SSL_CTX_new(SSLv23_server_method());
yanbzhu08ce6ab2015-12-02 13:01:29 -05003426 if (cur_ctx == NULL) {
3427 memprintf(err, "%sunable to allocate SSL context.\n",
3428 err && *err ? *err : "");
3429 rv = 1;
3430 goto end;
3431 }
3432
yanbzhube2774d2015-12-10 15:07:30 -05003433 /* Load all required certs/keys/chains/OCSPs info into SSL_CTX */
yanbzhu08ce6ab2015-12-02 13:01:29 -05003434 for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
3435 if (i & (1<<n)) {
3436 /* Key combo contains ckch[n] */
Bertrand Jacquin33423092016-11-13 16:37:13 +00003437 snprintf(cur_file, MAXPATHLEN+1, "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
3438 if (ssl_sock_put_ckch_into_ctx(cur_file, &certs_and_keys[n], cur_ctx, err) != 0) {
yanbzhu08ce6ab2015-12-02 13:01:29 -05003439 rv = 1;
3440 goto end;
3441 }
yanbzhube2774d2015-12-10 15:07:30 -05003442
yanbzhu08ce6ab2015-12-02 13:01:29 -05003443 }
3444 }
3445
yanbzhu08ce6ab2015-12-02 13:01:29 -05003446 /* Update key_combos */
3447 key_combos[i-1].ctx = cur_ctx;
3448 }
3449
3450 /* Update SNI Tree */
William Lallemand9117de92019-10-04 00:29:42 +02003451
William Lallemand1d29c742019-10-04 00:53:29 +02003452 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 +02003453 kinfo, str, key_combos[i-1].order);
3454 if (key_combos[i-1].order < 0) {
3455 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
3456 rv = 1;
3457 goto end;
3458 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003459 node = ebmb_next(node);
3460 }
3461
3462
3463 /* Mark a default context if none exists, using the ctx that has the most shared keys */
3464 if (!bind_conf->default_ctx) {
3465 for (i = SSL_SOCK_POSSIBLE_KT_COMBOS - 1; i >= 0; i--) {
3466 if (key_combos[i].ctx) {
3467 bind_conf->default_ctx = key_combos[i].ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003468 bind_conf->default_ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003469 break;
3470 }
3471 }
3472 }
3473
William Lallemand614ca0d2019-10-07 13:52:11 +02003474 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003475 ckch_inst->ssl_conf = ssl_conf;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003476end:
3477
3478 if (names)
3479 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
3480
yanbzhu08ce6ab2015-12-02 13:01:29 -05003481 node = ebmb_first(&sni_keytypes_map);
3482 while (node) {
3483 next = ebmb_next(node);
3484 ebmb_delete(node);
William Lallemand8ed5b962019-10-04 17:24:39 +02003485 free(ebmb_entry(node, struct sni_keytype, name));
yanbzhu08ce6ab2015-12-02 13:01:29 -05003486 node = next;
3487 }
3488
William Lallemand0c6d12f2019-10-04 18:38:51 +02003489 if (rv > 0) {
3490 struct sni_ctx *sc0, *sc0b;
3491
3492 /* free the SSL_CTX in case of error */
3493 for (i = 0; i < SSL_SOCK_POSSIBLE_KT_COMBOS; i++) {
3494 if (key_combos[i].ctx)
3495 SSL_CTX_free(key_combos[i].ctx);
3496 }
3497
3498 /* free the sni_ctx in case of error */
3499 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3500
3501 ebmb_delete(&sc0->name);
3502 LIST_DEL(&sc0->by_ckch_inst);
3503 free(sc0);
3504 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003505 free(ckch_inst);
3506 ckch_inst = NULL;
William Lallemand0c6d12f2019-10-04 18:38:51 +02003507 }
3508
William Lallemand614ca0d2019-10-07 13:52:11 +02003509 return ckch_inst;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003510}
3511#else
3512/* This is a dummy, that just logs an error and returns error */
William Lallemand614ca0d2019-10-07 13:52:11 +02003513static struct ckch_inst *ckch_inst_new_load_multi_store(const char *path, struct ckch_store *ckchs,
William Lallemand36b84632019-07-18 19:28:17 +02003514 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3515 char **sni_filter, int fcount, char **err)
yanbzhu08ce6ab2015-12-02 13:01:29 -05003516{
3517 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3518 err && *err ? *err : "", path, strerror(errno));
William Lallemand614ca0d2019-10-07 13:52:11 +02003519 return NULL;
yanbzhu08ce6ab2015-12-02 13:01:29 -05003520}
3521
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003522#endif /* #if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL: Support for loading multiple certs into a single SSL_CTX */
yanbzhu488a4d22015-12-01 15:16:07 -05003523
William Lallemand614ca0d2019-10-07 13:52:11 +02003524/*
3525 * This function allocate a ckch_inst and create its snis
3526 */
3527static struct ckch_inst *ckch_inst_new_load_store(const char *path, struct ckch_store *ckchs, struct bind_conf *bind_conf,
3528 struct ssl_bind_conf *ssl_conf, char **sni_filter, int fcount, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003529{
William Lallemandc9402072019-05-15 15:33:54 +02003530 SSL_CTX *ctx;
William Lallemandc9402072019-05-15 15:33:54 +02003531 int i;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003532 int order = 0;
3533 X509_NAME *xname;
3534 char *str;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003535 EVP_PKEY *pkey;
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003536 struct pkey_info kinfo = { .sig = TLSEXT_signature_anonymous, .bits = 0 };
Emeric Brunfc0421f2012-09-07 17:30:07 +02003537#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
3538 STACK_OF(GENERAL_NAME) *names;
3539#endif
William Lallemand36b84632019-07-18 19:28:17 +02003540 struct cert_key_and_chain *ckch;
William Lallemand614ca0d2019-10-07 13:52:11 +02003541 struct ckch_inst *ckch_inst = NULL;
William Lallemanda59191b2019-05-15 16:08:56 +02003542
William Lallemande3af8fb2019-10-08 11:36:53 +02003543 if (!ckchs || !ckchs->ckch)
William Lallemand614ca0d2019-10-07 13:52:11 +02003544 return NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003545
William Lallemande3af8fb2019-10-08 11:36:53 +02003546 ckch = ckchs->ckch;
William Lallemand36b84632019-07-18 19:28:17 +02003547
William Lallemand150bfa82019-09-19 17:12:49 +02003548 /* at least one of the instances is using filters during the config
3549 * parsing, that's ok to inherit this during loading on CLI */
3550 ckchs->filters = !!fcount;
3551
William Lallemandc9402072019-05-15 15:33:54 +02003552 ctx = SSL_CTX_new(SSLv23_server_method());
3553 if (!ctx) {
3554 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3555 err && *err ? *err : "", path);
William Lallemand614ca0d2019-10-07 13:52:11 +02003556 return NULL;
William Lallemandc9402072019-05-15 15:33:54 +02003557 }
3558
William Lallemand36b84632019-07-18 19:28:17 +02003559 if (ssl_sock_put_ckch_into_ctx(path, ckch, ctx, err) != 0) {
William Lallemand614ca0d2019-10-07 13:52:11 +02003560 goto error;
3561 }
3562
3563 ckch_inst = ckch_inst_new();
3564 if (!ckch_inst) {
3565 memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
3566 err && *err ? *err : "", path);
William Lallemandd9199372019-10-04 15:37:05 +02003567 goto error;
William Lallemandc9402072019-05-15 15:33:54 +02003568 }
3569
William Lallemand36b84632019-07-18 19:28:17 +02003570 pkey = X509_get_pubkey(ckch->cert);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003571 if (pkey) {
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003572 kinfo.bits = EVP_PKEY_bits(pkey);
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003573 switch(EVP_PKEY_base_id(pkey)) {
3574 case EVP_PKEY_RSA:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003575 kinfo.sig = TLSEXT_signature_rsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003576 break;
3577 case EVP_PKEY_EC:
Emmanuel Hocdetddc090b2017-10-27 18:43:29 +02003578 kinfo.sig = TLSEXT_signature_ecdsa;
3579 break;
3580 case EVP_PKEY_DSA:
3581 kinfo.sig = TLSEXT_signature_dsa;
Emmanuel Hocdet05942112017-02-20 16:11:50 +01003582 break;
3583 }
3584 EVP_PKEY_free(pkey);
3585 }
3586
Emeric Brun50bcecc2013-04-22 13:05:23 +02003587 if (fcount) {
William Lallemandfe49bb32019-10-03 23:46:33 +02003588 while (fcount--) {
William Lallemand1d29c742019-10-04 00:53:29 +02003589 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 +02003590 if (order < 0) {
3591 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
William Lallemandd9199372019-10-04 15:37:05 +02003592 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003593 }
3594 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003595 }
3596 else {
Emeric Brunfc0421f2012-09-07 17:30:07 +02003597#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
William Lallemand36b84632019-07-18 19:28:17 +02003598 names = X509_get_ext_d2i(ckch->cert, NID_subject_alt_name, NULL, NULL);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003599 if (names) {
3600 for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
3601 GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
3602 if (name->type == GEN_DNS) {
3603 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003604 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003605 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003606 if (order < 0) {
3607 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
William Lallemandd9199372019-10-04 15:37:05 +02003608 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003609 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003610 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003611 }
3612 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003613 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003614 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003615#endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
William Lallemand36b84632019-07-18 19:28:17 +02003616 xname = X509_get_subject_name(ckch->cert);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003617 i = -1;
3618 while ((i = X509_NAME_get_index_by_NID(xname, NID_commonName, i)) != -1) {
3619 X509_NAME_ENTRY *entry = X509_NAME_get_entry(xname, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02003620 ASN1_STRING *value;
3621
3622 value = X509_NAME_ENTRY_get_data(entry);
3623 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
William Lallemand1d29c742019-10-04 00:53:29 +02003624 order = ckch_inst_add_cert_sni(ctx, ckch_inst, bind_conf, ssl_conf, kinfo, str, order);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003625 OPENSSL_free(str);
William Lallemandfe49bb32019-10-03 23:46:33 +02003626 if (order < 0) {
3627 memprintf(err, "%sunable to create a sni context.\n", err && *err ? *err : "");
William Lallemandd9199372019-10-04 15:37:05 +02003628 goto error;
William Lallemandfe49bb32019-10-03 23:46:33 +02003629 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003630 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003631 }
3632 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003633 /* we must not free the SSL_CTX anymore below, since it's already in
3634 * the tree, so it will be discovered and cleaned in time.
3635 */
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02003636
Emeric Brunfc0421f2012-09-07 17:30:07 +02003637#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003638 if (bind_conf->default_ctx) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02003639 memprintf(err, "%sthis version of openssl cannot load multiple SSL certificates.\n",
3640 err && *err ? *err : "");
William Lallemandd9199372019-10-04 15:37:05 +02003641 goto error;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003642 }
3643#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003644 if (!bind_conf->default_ctx) {
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003645 bind_conf->default_ctx = ctx;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003646 bind_conf->default_ssl_conf = ssl_conf;
3647 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003648
William Lallemand9117de92019-10-04 00:29:42 +02003649 /* everything succeed, the ckch instance can be used */
3650 ckch_inst->bind_conf = bind_conf;
William Lallemand150bfa82019-09-19 17:12:49 +02003651 ckch_inst->ssl_conf = ssl_conf;
William Lallemand9117de92019-10-04 00:29:42 +02003652
William Lallemand614ca0d2019-10-07 13:52:11 +02003653 return ckch_inst;
William Lallemandd9199372019-10-04 15:37:05 +02003654
3655error:
3656 /* free the allocated sni_ctxs */
William Lallemand614ca0d2019-10-07 13:52:11 +02003657 if (ckch_inst) {
William Lallemandd9199372019-10-04 15:37:05 +02003658 struct sni_ctx *sc0, *sc0b;
3659
3660 list_for_each_entry_safe(sc0, sc0b, &ckch_inst->sni_ctx, by_ckch_inst) {
3661
3662 ebmb_delete(&sc0->name);
3663 LIST_DEL(&sc0->by_ckch_inst);
3664 free(sc0);
3665 }
William Lallemand614ca0d2019-10-07 13:52:11 +02003666 free(ckch_inst);
3667 ckch_inst = NULL;
William Lallemandd9199372019-10-04 15:37:05 +02003668 }
3669 /* We only created 1 SSL_CTX so we can free it there */
3670 SSL_CTX_free(ctx);
3671
William Lallemand614ca0d2019-10-07 13:52:11 +02003672 return NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003673}
3674
William Lallemand614ca0d2019-10-07 13:52:11 +02003675static int ssl_sock_load_ckchs(const char *path, struct ckch_store *ckchs,
3676 struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
3677 char **sni_filter, int fcount, char **err)
3678{
3679 struct ckch_inst *ckch_inst = NULL;
3680
3681 /* we found the ckchs in the tree, we can use it directly */
3682 if (ckchs->multi)
3683 ckch_inst = ckch_inst_new_load_multi_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, err);
3684 else
3685 ckch_inst = ckch_inst_new_load_store(path, ckchs, bind_conf, ssl_conf, sni_filter, fcount, err);
3686
3687 if (!ckch_inst)
3688 return 1;
3689
3690 ssl_sock_load_cert_sni(ckch_inst, bind_conf);
3691
3692 /* succeed, add the instance to the ckch_store's list of instance */
3693 LIST_ADDQ(&ckchs->ckch_inst, &ckch_inst->by_ckchs);
3694
3695 return 0;
3696}
3697
3698
Willy Tarreau03209342016-12-22 17:08:28 +01003699int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
Emeric Brunfc0421f2012-09-07 17:30:07 +02003700{
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003701 struct dirent **de_list;
3702 int i, n;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003703 DIR *dir;
3704 struct stat buf;
Willy Tarreauee2663b2012-12-06 11:36:59 +01003705 char *end;
3706 char fp[MAXPATHLEN+1];
Emeric Brunfc0421f2012-09-07 17:30:07 +02003707 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003708 struct ckch_store *ckchs;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003709#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003710 int is_bundle;
3711 int j;
3712#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003713 if ((ckchs = ckchs_lookup(path))) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003714 /* we found the ckchs in the tree, we can use it directly */
William Lallemand614ca0d2019-10-07 13:52:11 +02003715 cfgerr = ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
3716 return cfgerr;
William Lallemand6af03992019-07-23 15:00:54 +02003717 }
3718
yanbzhu08ce6ab2015-12-02 13:01:29 -05003719 if (stat(path, &buf) == 0) {
3720 dir = opendir(path);
William Lallemand36b84632019-07-18 19:28:17 +02003721 if (!dir) {
William Lallemande3af8fb2019-10-08 11:36:53 +02003722 ckchs = ckchs_load_cert_file(path, 0, err);
3723 if (!ckchs)
William Lallemand36b84632019-07-18 19:28:17 +02003724 return 1;
William Lallemand614ca0d2019-10-07 13:52:11 +02003725 cfgerr = ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
3726 return cfgerr;
William Lallemand36b84632019-07-18 19:28:17 +02003727 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02003728
yanbzhu08ce6ab2015-12-02 13:01:29 -05003729 /* strip trailing slashes, including first one */
3730 for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
3731 *end = 0;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003732
yanbzhu08ce6ab2015-12-02 13:01:29 -05003733 n = scandir(path, &de_list, 0, alphasort);
3734 if (n < 0) {
3735 memprintf(err, "%sunable to scan directory '%s' : %s.\n",
3736 err && *err ? *err : "", path, strerror(errno));
3737 cfgerr++;
3738 }
3739 else {
3740 for (i = 0; i < n; i++) {
3741 struct dirent *de = de_list[i];
Emeric Brun2aab7222014-06-18 18:15:09 +02003742
yanbzhu08ce6ab2015-12-02 13:01:29 -05003743 end = strrchr(de->d_name, '.');
3744 if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl")))
3745 goto ignore_entry;
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003746
yanbzhu08ce6ab2015-12-02 13:01:29 -05003747 snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
3748 if (stat(fp, &buf) != 0) {
3749 memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
3750 err && *err ? *err : "", fp, strerror(errno));
3751 cfgerr++;
3752 goto ignore_entry;
3753 }
3754 if (!S_ISREG(buf.st_mode))
3755 goto ignore_entry;
yanbzhu63ea8462015-12-09 13:35:14 -05003756
Willy Tarreau9a1ab082019-05-09 13:26:41 +02003757#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
yanbzhu63ea8462015-12-09 13:35:14 -05003758 is_bundle = 0;
3759 /* Check if current entry in directory is part of a multi-cert bundle */
3760
3761 if (end) {
3762 for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
3763 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
3764 is_bundle = 1;
3765 break;
3766 }
3767 }
3768
3769 if (is_bundle) {
3770 char dp[MAXPATHLEN+1] = {0}; /* this will be the filename w/o the keytype */
3771 int dp_len;
3772
3773 dp_len = end - de->d_name;
3774 snprintf(dp, dp_len + 1, "%s", de->d_name);
3775
3776 /* increment i and free de until we get to a non-bundle cert
3777 * Note here that we look at de_list[i + 1] before freeing de
3778 * this is important since ignore_entry will free de
3779 */
3780 while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, dp, dp_len)) {
3781 free(de);
3782 i++;
3783 de = de_list[i];
3784 }
3785
3786 snprintf(fp, sizeof(fp), "%s/%s", path, dp);
William Lallemande3af8fb2019-10-08 11:36:53 +02003787 if ((ckchs = ckchs_lookup(fp)) == NULL)
3788 ckchs = ckchs_load_cert_file(fp, 1, err);
3789 if (!ckchs)
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02003790 cfgerr++;
William Lallemand614ca0d2019-10-07 13:52:11 +02003791 else
3792 cfgerr += ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu63ea8462015-12-09 13:35:14 -05003793 /* Successfully processed the bundle */
3794 goto ignore_entry;
3795 }
3796 }
3797
3798#endif
William Lallemande3af8fb2019-10-08 11:36:53 +02003799 if ((ckchs = ckchs_lookup(fp)) == NULL)
3800 ckchs = ckchs_load_cert_file(fp, 0, err);
3801 if (!ckchs)
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02003802 cfgerr++;
William Lallemand614ca0d2019-10-07 13:52:11 +02003803 else
3804 cfgerr += ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
William Lallemand36b84632019-07-18 19:28:17 +02003805
yanbzhu08ce6ab2015-12-02 13:01:29 -05003806ignore_entry:
3807 free(de);
Cyril Bonté3180f7b2015-01-25 00:16:08 +01003808 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003809 free(de_list);
Emeric Brunfc0421f2012-09-07 17:30:07 +02003810 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003811 closedir(dir);
3812 return cfgerr;
Emeric Brunfc0421f2012-09-07 17:30:07 +02003813 }
yanbzhu08ce6ab2015-12-02 13:01:29 -05003814
William Lallemande3af8fb2019-10-08 11:36:53 +02003815 ckchs = ckchs_load_cert_file(path, 1, err);
3816 if (!ckchs)
William Lallemand36b84632019-07-18 19:28:17 +02003817 return 1;
William Lallemand614ca0d2019-10-07 13:52:11 +02003818 cfgerr += ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
yanbzhu08ce6ab2015-12-02 13:01:29 -05003819
Emeric Brunfc0421f2012-09-07 17:30:07 +02003820 return cfgerr;
3821}
3822
Thierry Fournier383085f2013-01-24 14:15:43 +01003823/* Make sure openssl opens /dev/urandom before the chroot. The work is only
3824 * done once. Zero is returned if the operation fails. No error is returned
3825 * if the random is said as not implemented, because we expect that openssl
3826 * will use another method once needed.
3827 */
3828static int ssl_initialize_random()
3829{
3830 unsigned char random;
3831 static int random_initialized = 0;
3832
3833 if (!random_initialized && RAND_bytes(&random, 1) != 0)
3834 random_initialized = 1;
3835
3836 return random_initialized;
3837}
3838
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003839/* release ssl bind conf */
3840void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf)
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003841{
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003842 if (conf) {
Bernard Spil13c53f82018-02-15 13:34:58 +01003843#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003844 free(conf->npn_str);
3845 conf->npn_str = NULL;
3846#endif
3847#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
3848 free(conf->alpn_str);
3849 conf->alpn_str = NULL;
3850#endif
3851 free(conf->ca_file);
3852 conf->ca_file = NULL;
3853 free(conf->crl_file);
3854 conf->crl_file = NULL;
3855 free(conf->ciphers);
3856 conf->ciphers = NULL;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02003857#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02003858 free(conf->ciphersuites);
3859 conf->ciphersuites = NULL;
3860#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01003861 free(conf->curves);
3862 conf->curves = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003863 free(conf->ecdhe);
3864 conf->ecdhe = NULL;
3865 }
3866}
3867
3868int ssl_sock_load_cert_list_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, char **err)
3869{
3870 char thisline[CRT_LINESIZE];
3871 char path[MAXPATHLEN+1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003872 FILE *f;
yanbzhu1b04e5b2015-12-02 13:54:14 -05003873 struct stat buf;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003874 int linenum = 0;
3875 int cfgerr = 0;
William Lallemande3af8fb2019-10-08 11:36:53 +02003876 struct ckch_store *ckchs;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003877
Willy Tarreauad1731d2013-04-02 17:35:58 +02003878 if ((f = fopen(file, "r")) == NULL) {
3879 memprintf(err, "cannot open file '%s' : %s", file, strerror(errno));
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003880 return 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003881 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003882
3883 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003884 int arg, newarg, cur_arg, i, ssl_b = 0, ssl_e = 0;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003885 char *end;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003886 char *args[MAX_CRT_ARGS + 1];
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003887 char *line = thisline;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003888 char *crt_path;
3889 struct ssl_bind_conf *ssl_conf = NULL;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003890
3891 linenum++;
3892 end = line + strlen(line);
3893 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
3894 /* Check if we reached the limit and the last char is not \n.
3895 * Watch out for the last line without the terminating '\n'!
3896 */
Willy Tarreauad1731d2013-04-02 17:35:58 +02003897 memprintf(err, "line %d too long in file '%s', limit is %d characters",
3898 linenum, file, (int)sizeof(thisline)-1);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003899 cfgerr = 1;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003900 break;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003901 }
3902
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003903 arg = 0;
Emeric Brun50bcecc2013-04-22 13:05:23 +02003904 newarg = 1;
3905 while (*line) {
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003906 if (*line == '#' || *line == '\n' || *line == '\r') {
3907 /* end of string, end of loop */
3908 *line = 0;
3909 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003910 } else if (isspace(*line)) {
Emeric Brun50bcecc2013-04-22 13:05:23 +02003911 newarg = 1;
3912 *line = 0;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003913 } else if (*line == '[') {
3914 if (ssl_b) {
3915 memprintf(err, "too many '[' on line %d in file '%s'.", linenum, file);
3916 cfgerr = 1;
3917 break;
3918 }
3919 if (!arg) {
3920 memprintf(err, "file must start with a cert on line %d in file '%s'", linenum, file);
3921 cfgerr = 1;
3922 break;
3923 }
3924 ssl_b = arg;
3925 newarg = 1;
3926 *line = 0;
3927 } else if (*line == ']') {
3928 if (ssl_e) {
3929 memprintf(err, "too many ']' on line %d in file '%s'.", linenum, file);
Emeric Brun50bcecc2013-04-22 13:05:23 +02003930 cfgerr = 1;
3931 break;
3932 }
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003933 if (!ssl_b) {
3934 memprintf(err, "missing '[' in line %d in file '%s'.", linenum, file);
3935 cfgerr = 1;
3936 break;
3937 }
3938 ssl_e = arg;
3939 newarg = 1;
3940 *line = 0;
3941 } else if (newarg) {
3942 if (arg == MAX_CRT_ARGS) {
3943 memprintf(err, "too many args on line %d in file '%s'.", linenum, file);
3944 cfgerr = 1;
3945 break;
3946 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003947 newarg = 0;
3948 args[arg++] = line;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003949 }
Emeric Brun50bcecc2013-04-22 13:05:23 +02003950 line++;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003951 }
Emmanuel Hocdet7c41a1b2013-05-07 20:20:06 +02003952 if (cfgerr)
3953 break;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003954 args[arg++] = line;
Willy Tarreauad1731d2013-04-02 17:35:58 +02003955
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003956 /* empty line */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003957 if (!*args[0])
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003958 continue;
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01003959
Emmanuel Hocdet98263292016-12-29 18:26:15 +01003960 crt_path = args[0];
3961 if (*crt_path != '/' && global_ssl.crt_base) {
3962 if ((strlen(global_ssl.crt_base) + 1 + strlen(crt_path)) > MAXPATHLEN) {
3963 memprintf(err, "'%s' : path too long on line %d in file '%s'",
3964 crt_path, linenum, file);
3965 cfgerr = 1;
3966 break;
3967 }
3968 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, crt_path);
3969 crt_path = path;
3970 }
3971
3972 ssl_conf = calloc(1, sizeof *ssl_conf);
3973 cur_arg = ssl_b ? ssl_b : 1;
3974 while (cur_arg < ssl_e) {
3975 newarg = 0;
3976 for (i = 0; ssl_bind_kws[i].kw != NULL; i++) {
3977 if (strcmp(ssl_bind_kws[i].kw, args[cur_arg]) == 0) {
3978 newarg = 1;
3979 cfgerr = ssl_bind_kws[i].parse(args, cur_arg, curproxy, ssl_conf, err);
3980 if (cur_arg + 1 + ssl_bind_kws[i].skip > ssl_e) {
3981 memprintf(err, "ssl args out of '[]' for %s on line %d in file '%s'",
3982 args[cur_arg], linenum, file);
3983 cfgerr = 1;
3984 }
3985 cur_arg += 1 + ssl_bind_kws[i].skip;
3986 break;
3987 }
3988 }
3989 if (!cfgerr && !newarg) {
3990 memprintf(err, "unknown ssl keyword %s on line %d in file '%s'.",
3991 args[cur_arg], linenum, file);
3992 cfgerr = 1;
3993 break;
3994 }
3995 }
3996 if (cfgerr) {
3997 ssl_sock_free_ssl_conf(ssl_conf);
3998 free(ssl_conf);
3999 ssl_conf = NULL;
4000 break;
4001 }
4002
William Lallemande3af8fb2019-10-08 11:36:53 +02004003 if ((ckchs = ckchs_lookup(crt_path)) == NULL) {
William Lallemandeed4bf22019-10-10 11:38:13 +02004004 if (stat(crt_path, &buf) == 0)
William Lallemande3af8fb2019-10-08 11:36:53 +02004005 ckchs = ckchs_load_cert_file(crt_path, 0, err);
Emmanuel Hocdet1503e052019-07-31 18:30:33 +02004006 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004007 ckchs = ckchs_load_cert_file(crt_path, 1, err);
yanbzhu1b04e5b2015-12-02 13:54:14 -05004008 }
4009
William Lallemande3af8fb2019-10-08 11:36:53 +02004010 if (!ckchs)
William Lallemandeed4bf22019-10-10 11:38:13 +02004011 cfgerr++;
4012 else
William Lallemande3af8fb2019-10-08 11:36:53 +02004013 cfgerr += ssl_sock_load_ckchs(crt_path, ckchs, bind_conf, ssl_conf,
William Lallemandeed4bf22019-10-10 11:38:13 +02004014 &args[cur_arg], arg - cur_arg - 1, err);
4015
Willy Tarreauad1731d2013-04-02 17:35:58 +02004016 if (cfgerr) {
4017 memprintf(err, "error processing line %d in file '%s' : %s", linenum, file, *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004018 break;
Willy Tarreauad1731d2013-04-02 17:35:58 +02004019 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004020 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01004021 fclose(f);
4022 return cfgerr;
4023}
4024
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004025/* Create an initial CTX used to start the SSL connection before switchctx */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004026static int
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004027ssl_sock_initial_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02004028{
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004029 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004030 long options =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004031 SSL_OP_ALL | /* all known workarounds for bugs */
4032 SSL_OP_NO_SSLv2 |
4033 SSL_OP_NO_COMPRESSION |
Emeric Bruna4bcd9a2012-09-20 16:19:02 +02004034 SSL_OP_SINGLE_DH_USE |
Emeric Brun2b58d042012-09-20 17:10:03 +02004035 SSL_OP_SINGLE_ECDH_USE |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004036 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
Lukas Tribus926594f2018-05-18 17:55:57 +02004037 SSL_OP_PRIORITIZE_CHACHA |
Emeric Brun3c4bc6e2012-10-04 18:44:19 +02004038 SSL_OP_CIPHER_SERVER_PREFERENCE;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004039 long mode =
Emeric Brunfc0421f2012-09-07 17:30:07 +02004040 SSL_MODE_ENABLE_PARTIAL_WRITE |
4041 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004042 SSL_MODE_RELEASE_BUFFERS |
4043 SSL_MODE_SMALL_BUFFERS;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004044 struct tls_version_filter *conf_ssl_methods = &bind_conf->ssl_conf.ssl_methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004045 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004046 int flags = MC_SSL_O_ALL;
4047 int cfgerr = 0;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004048
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004049 ctx = SSL_CTX_new(SSLv23_server_method());
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004050 bind_conf->initial_ctx = ctx;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004051
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004052 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004053 ha_warning("Proxy '%s': no-sslv3/no-tlsv1x are ignored for bind '%s' at [%s:%d]. "
4054 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4055 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004056 else
4057 flags = conf_ssl_methods->flags;
4058
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004059 min = conf_ssl_methods->min;
4060 max = conf_ssl_methods->max;
4061 /* start with TLSv10 to remove SSLv3 per default */
4062 if (!min && (!max || max >= CONF_TLSV10))
4063 min = CONF_TLSV10;
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004064 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdetbd695fe2017-05-15 15:53:41 +02004065 if (min)
4066 flags |= (methodVersions[min].flag - 1);
4067 if (max)
4068 flags |= ~((methodVersions[max].flag << 1) - 1);
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004069 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004070 min = max = CONF_TLSV_NONE;
4071 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004072 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004073 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004074 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004075 if (min) {
4076 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004077 ha_warning("Proxy '%s': SSL/TLS versions range not contiguous for bind '%s' at [%s:%d]. "
4078 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4079 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line,
4080 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004081 hole = 0;
4082 }
4083 max = i;
4084 }
4085 else {
4086 min = max = i;
4087 }
4088 }
4089 else {
4090 if (min)
4091 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004092 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004093 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004094 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4095 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004096 cfgerr += 1;
4097 }
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004098 /* save real min/max in bind_conf */
4099 conf_ssl_methods->min = min;
4100 conf_ssl_methods->max = max;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004101
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004102#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004103 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004104 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004105 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004106 methodVersions[min].ctx_set_version(ctx, SET_SERVER);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004107 else
4108 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4109 if (flags & methodVersions[i].flag)
4110 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004111#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004112 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004113 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4114 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emeric Brunfa5c5c82017-04-28 16:19:51 +02004115#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004116
4117 if (bind_conf->ssl_options & BC_SSL_O_NO_TLS_TICKETS)
4118 options |= SSL_OP_NO_TICKET;
4119 if (bind_conf->ssl_options & BC_SSL_O_PREF_CLIE_CIPH)
4120 options &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
Dirkjan Bussink526894f2019-01-21 09:35:03 -08004121
4122#ifdef SSL_OP_NO_RENEGOTIATION
4123 options |= SSL_OP_NO_RENEGOTIATION;
4124#endif
4125
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004126 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004127
Willy Tarreau5db847a2019-05-09 14:13:35 +02004128#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004129 if (global_ssl.async)
4130 mode |= SSL_MODE_ASYNC;
4131#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004132 SSL_CTX_set_mode(ctx, mode);
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004133 if (global_ssl.life_time)
4134 SSL_CTX_set_timeout(ctx, global_ssl.life_time);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004135
4136#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
4137#ifdef OPENSSL_IS_BORINGSSL
4138 SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk);
4139 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Willy Tarreau5db847a2019-05-09 14:13:35 +02004140#elif (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard51088ce2019-01-02 18:46:41 +01004141 if (bind_conf->ssl_conf.early_data) {
4142 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
4143 SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite);
4144 }
Emmanuel Hocdet84e417d2017-08-16 11:33:17 +02004145 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
4146 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004147#else
4148 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004149#endif
Emmanuel Hocdet253c62b2017-08-14 11:01:25 +02004150 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01004151#endif
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004152 return cfgerr;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004153}
4154
William Lallemand4f45bb92017-10-30 20:08:51 +01004155
4156static inline void sh_ssl_sess_free_blocks(struct shared_block *first, struct shared_block *block)
4157{
4158 if (first == block) {
4159 struct sh_ssl_sess_hdr *sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4160 if (first->len > 0)
4161 sh_ssl_sess_tree_delete(sh_ssl_sess);
4162 }
4163}
4164
4165/* return first block from sh_ssl_sess */
4166static inline struct shared_block *sh_ssl_sess_first_block(struct sh_ssl_sess_hdr *sh_ssl_sess)
4167{
4168 return (struct shared_block *)((unsigned char *)sh_ssl_sess - ((struct shared_block *)NULL)->data);
4169
4170}
4171
4172/* store a session into the cache
4173 * s_id : session id padded with zero to SSL_MAX_SSL_SESSION_ID_LENGTH
4174 * data: asn1 encoded session
4175 * data_len: asn1 encoded session length
4176 * Returns 1 id session was stored (else 0)
4177 */
4178static int sh_ssl_sess_store(unsigned char *s_id, unsigned char *data, int data_len)
4179{
4180 struct shared_block *first;
4181 struct sh_ssl_sess_hdr *sh_ssl_sess, *oldsh_ssl_sess;
4182
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004183 first = shctx_row_reserve_hot(ssl_shctx, NULL, data_len + sizeof(struct sh_ssl_sess_hdr));
William Lallemand4f45bb92017-10-30 20:08:51 +01004184 if (!first) {
4185 /* Could not retrieve enough free blocks to store that session */
4186 return 0;
4187 }
4188
4189 /* STORE the key in the first elem */
4190 sh_ssl_sess = (struct sh_ssl_sess_hdr *)first->data;
4191 memcpy(sh_ssl_sess->key_data, s_id, SSL_MAX_SSL_SESSION_ID_LENGTH);
4192 first->len = sizeof(struct sh_ssl_sess_hdr);
4193
4194 /* it returns the already existing node
4195 or current node if none, never returns null */
4196 oldsh_ssl_sess = sh_ssl_sess_tree_insert(sh_ssl_sess);
4197 if (oldsh_ssl_sess != sh_ssl_sess) {
4198 /* NOTE: Row couldn't be in use because we lock read & write function */
4199 /* release the reserved row */
4200 shctx_row_dec_hot(ssl_shctx, first);
4201 /* replace the previous session already in the tree */
4202 sh_ssl_sess = oldsh_ssl_sess;
4203 /* ignore the previous session data, only use the header */
4204 first = sh_ssl_sess_first_block(sh_ssl_sess);
4205 shctx_row_inc_hot(ssl_shctx, first);
4206 first->len = sizeof(struct sh_ssl_sess_hdr);
4207 }
4208
Frédéric Lécaille0bec8072018-10-22 17:55:57 +02004209 if (shctx_row_data_append(ssl_shctx, first, NULL, data, data_len) < 0) {
William Lallemand99b90af2018-01-03 19:15:51 +01004210 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004211 return 0;
William Lallemand99b90af2018-01-03 19:15:51 +01004212 }
4213
4214 shctx_row_dec_hot(ssl_shctx, first);
William Lallemand4f45bb92017-10-30 20:08:51 +01004215
4216 return 1;
4217}
William Lallemanded0b5ad2017-10-30 19:36:36 +01004218
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004219/* SSL callback used when a new session is created while connecting to a server */
4220static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
4221{
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004222 struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houcharde6060c52017-11-16 17:42:52 +01004223 struct server *s;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004224
Willy Tarreau07d94e42018-09-20 10:57:52 +02004225 s = __objt_server(conn->target);
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004226
Olivier Houcharde6060c52017-11-16 17:42:52 +01004227 if (!(s->ssl_ctx.options & SRV_SSL_O_NO_REUSE)) {
4228 int len;
4229 unsigned char *ptr;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004230
Olivier Houcharde6060c52017-11-16 17:42:52 +01004231 len = i2d_SSL_SESSION(sess, NULL);
4232 if (s->ssl_ctx.reused_sess[tid].ptr && s->ssl_ctx.reused_sess[tid].allocated_size >= len) {
4233 ptr = s->ssl_ctx.reused_sess[tid].ptr;
4234 } else {
4235 free(s->ssl_ctx.reused_sess[tid].ptr);
4236 ptr = s->ssl_ctx.reused_sess[tid].ptr = malloc(len);
4237 s->ssl_ctx.reused_sess[tid].allocated_size = len;
4238 }
4239 if (s->ssl_ctx.reused_sess[tid].ptr) {
4240 s->ssl_ctx.reused_sess[tid].size = i2d_SSL_SESSION(sess,
4241 &ptr);
4242 }
4243 } else {
4244 free(s->ssl_ctx.reused_sess[tid].ptr);
4245 s->ssl_ctx.reused_sess[tid].ptr = NULL;
4246 }
4247
4248 return 0;
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004249}
4250
Olivier Houcharde6060c52017-11-16 17:42:52 +01004251
William Lallemanded0b5ad2017-10-30 19:36:36 +01004252/* SSL callback used on new session creation */
William Lallemand4f45bb92017-10-30 20:08:51 +01004253int sh_ssl_sess_new_cb(SSL *ssl, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004254{
4255 unsigned char encsess[SHSESS_MAX_DATA_LEN]; /* encoded session */
4256 unsigned char encid[SSL_MAX_SSL_SESSION_ID_LENGTH]; /* encoded id */
4257 unsigned char *p;
4258 int data_len;
4259 unsigned int sid_length, sid_ctx_length;
4260 const unsigned char *sid_data;
4261 const unsigned char *sid_ctx_data;
4262
4263 /* Session id is already stored in to key and session id is known
4264 * so we dont store it to keep size.
4265 */
4266
4267 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4268 sid_ctx_data = SSL_SESSION_get0_id_context(sess, &sid_ctx_length);
4269 SSL_SESSION_set1_id(sess, sid_data, 0);
4270 SSL_SESSION_set1_id_context(sess, sid_ctx_data, 0);
4271
4272 /* check if buffer is large enough for the ASN1 encoded session */
4273 data_len = i2d_SSL_SESSION(sess, NULL);
4274 if (data_len > SHSESS_MAX_DATA_LEN)
4275 goto err;
4276
4277 p = encsess;
4278
4279 /* process ASN1 session encoding before the lock */
4280 i2d_SSL_SESSION(sess, &p);
4281
4282 memcpy(encid, sid_data, sid_length);
4283 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH)
4284 memset(encid + sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH-sid_length);
4285
William Lallemanda3c77cf2017-10-30 23:44:40 +01004286 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004287 /* store to cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004288 sh_ssl_sess_store(encid, encsess, data_len);
William Lallemanda3c77cf2017-10-30 23:44:40 +01004289 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004290err:
4291 /* reset original length values */
4292 SSL_SESSION_set1_id(sess, sid_data, sid_length);
4293 SSL_SESSION_set1_id_context(sess, sid_ctx_data, sid_ctx_length);
4294
4295 return 0; /* do not increment session reference count */
4296}
4297
4298/* SSL callback used on lookup an existing session cause none found in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004299SSL_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 +01004300{
William Lallemand4f45bb92017-10-30 20:08:51 +01004301 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004302 unsigned char data[SHSESS_MAX_DATA_LEN], *p;
4303 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
William Lallemanded0b5ad2017-10-30 19:36:36 +01004304 SSL_SESSION *sess;
William Lallemand4f45bb92017-10-30 20:08:51 +01004305 struct shared_block *first;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004306
4307 global.shctx_lookups++;
4308
4309 /* allow the session to be freed automatically by openssl */
4310 *do_copy = 0;
4311
4312 /* tree key is zeros padded sessionid */
4313 if (key_len < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4314 memcpy(tmpkey, key, key_len);
4315 memset(tmpkey + key_len, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - key_len);
4316 key = tmpkey;
4317 }
4318
4319 /* lock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004320 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004321
4322 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004323 sh_ssl_sess = sh_ssl_sess_tree_lookup(key);
4324 if (!sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004325 /* no session found: unlock cache and exit */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004326 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004327 global.shctx_misses++;
4328 return NULL;
4329 }
4330
William Lallemand4f45bb92017-10-30 20:08:51 +01004331 /* sh_ssl_sess (shared_block->data) is at the end of shared_block */
4332 first = sh_ssl_sess_first_block(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004333
William Lallemand4f45bb92017-10-30 20:08:51 +01004334 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 +01004335
William Lallemanda3c77cf2017-10-30 23:44:40 +01004336 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004337
4338 /* decode ASN1 session */
4339 p = data;
William Lallemand4f45bb92017-10-30 20:08:51 +01004340 sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&p, first->len-sizeof(struct sh_ssl_sess_hdr));
William Lallemanded0b5ad2017-10-30 19:36:36 +01004341 /* Reset session id and session id contenxt */
4342 if (sess) {
4343 SSL_SESSION_set1_id(sess, key, key_len);
4344 SSL_SESSION_set1_id_context(sess, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4345 }
4346
4347 return sess;
4348}
4349
William Lallemand4f45bb92017-10-30 20:08:51 +01004350
William Lallemanded0b5ad2017-10-30 19:36:36 +01004351/* SSL callback used to signal session is no more used in internal cache */
William Lallemand4f45bb92017-10-30 20:08:51 +01004352void sh_ssl_sess_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004353{
William Lallemand4f45bb92017-10-30 20:08:51 +01004354 struct sh_ssl_sess_hdr *sh_ssl_sess;
William Lallemanded0b5ad2017-10-30 19:36:36 +01004355 unsigned char tmpkey[SSL_MAX_SSL_SESSION_ID_LENGTH];
4356 unsigned int sid_length;
4357 const unsigned char *sid_data;
4358 (void)ctx;
4359
4360 sid_data = SSL_SESSION_get_id(sess, &sid_length);
4361 /* tree key is zeros padded sessionid */
4362 if (sid_length < SSL_MAX_SSL_SESSION_ID_LENGTH) {
4363 memcpy(tmpkey, sid_data, sid_length);
4364 memset(tmpkey+sid_length, 0, SSL_MAX_SSL_SESSION_ID_LENGTH - sid_length);
4365 sid_data = tmpkey;
4366 }
4367
William Lallemanda3c77cf2017-10-30 23:44:40 +01004368 shctx_lock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004369
4370 /* lookup for session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004371 sh_ssl_sess = sh_ssl_sess_tree_lookup(sid_data);
4372 if (sh_ssl_sess) {
William Lallemanded0b5ad2017-10-30 19:36:36 +01004373 /* free session */
William Lallemand4f45bb92017-10-30 20:08:51 +01004374 sh_ssl_sess_tree_delete(sh_ssl_sess);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004375 }
4376
4377 /* unlock cache */
William Lallemanda3c77cf2017-10-30 23:44:40 +01004378 shctx_unlock(ssl_shctx);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004379}
4380
4381/* Set session cache mode to server and disable openssl internal cache.
4382 * Set shared cache callbacks on an ssl context.
4383 * Shared context MUST be firstly initialized */
William Lallemand4f45bb92017-10-30 20:08:51 +01004384void ssl_set_shctx(SSL_CTX *ctx)
William Lallemanded0b5ad2017-10-30 19:36:36 +01004385{
4386 SSL_CTX_set_session_id_context(ctx, (const unsigned char *)SHCTX_APPNAME, strlen(SHCTX_APPNAME));
4387
4388 if (!ssl_shctx) {
4389 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
4390 return;
4391 }
4392
4393 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER |
4394 SSL_SESS_CACHE_NO_INTERNAL |
4395 SSL_SESS_CACHE_NO_AUTO_CLEAR);
4396
4397 /* Set callbacks */
William Lallemand4f45bb92017-10-30 20:08:51 +01004398 SSL_CTX_sess_set_new_cb(ctx, sh_ssl_sess_new_cb);
4399 SSL_CTX_sess_set_get_cb(ctx, sh_ssl_sess_get_cb);
4400 SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
William Lallemanded0b5ad2017-10-30 19:36:36 +01004401}
4402
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004403int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx)
4404{
4405 struct proxy *curproxy = bind_conf->frontend;
4406 int cfgerr = 0;
4407 int verify = SSL_VERIFY_NONE;
Willy Tarreau5d4cafb2018-01-04 18:55:19 +01004408 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004409 const char *conf_ciphers;
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004410#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004411 const char *conf_ciphersuites;
4412#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004413 const char *conf_curves = NULL;
Emeric Brunfc0421f2012-09-07 17:30:07 +02004414
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004415 if (ssl_conf) {
4416 struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
4417 int i, min, max;
4418 int flags = MC_SSL_O_ALL;
4419
4420 /* Real min and max should be determinate with configuration and openssl's capabilities */
Emmanuel Hocdet43664762017-08-09 18:26:20 +02004421 min = conf_ssl_methods->min ? conf_ssl_methods->min : bind_conf->ssl_conf.ssl_methods.min;
4422 max = conf_ssl_methods->max ? conf_ssl_methods->max : bind_conf->ssl_conf.ssl_methods.max;
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004423 if (min)
4424 flags |= (methodVersions[min].flag - 1);
4425 if (max)
4426 flags |= ~((methodVersions[max].flag << 1) - 1);
4427 min = max = CONF_TLSV_NONE;
4428 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4429 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
4430 if (min)
4431 max = i;
4432 else
4433 min = max = i;
4434 }
4435 /* save real min/max */
4436 conf_ssl_methods->min = min;
4437 conf_ssl_methods->max = max;
4438 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004439 ha_alert("Proxy '%s': all SSL/TLS versions are disabled for bind '%s' at [%s:%d].\n",
4440 bind_conf->frontend->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02004441 cfgerr += 1;
4442 }
4443 }
4444
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004445 switch ((ssl_conf && ssl_conf->verify) ? ssl_conf->verify : bind_conf->ssl_conf.verify) {
Emeric Brun850efd52014-01-29 12:24:34 +01004446 case SSL_SOCK_VERIFY_NONE:
4447 verify = SSL_VERIFY_NONE;
4448 break;
4449 case SSL_SOCK_VERIFY_OPTIONAL:
4450 verify = SSL_VERIFY_PEER;
4451 break;
4452 case SSL_SOCK_VERIFY_REQUIRED:
4453 verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
4454 break;
4455 }
4456 SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
4457 if (verify & SSL_VERIFY_PEER) {
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004458 char *ca_file = (ssl_conf && ssl_conf->ca_file) ? ssl_conf->ca_file : bind_conf->ssl_conf.ca_file;
4459 char *crl_file = (ssl_conf && ssl_conf->crl_file) ? ssl_conf->crl_file : bind_conf->ssl_conf.crl_file;
4460 if (ca_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004461 /* load CAfile to verify */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004462 if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004463 ha_alert("Proxy '%s': unable to load CA file '%s' for bind '%s' at [%s:%d].\n",
4464 curproxy->id, ca_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004465 cfgerr++;
4466 }
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02004467 if (!((ssl_conf && ssl_conf->no_ca_names) || bind_conf->ssl_conf.no_ca_names)) {
4468 /* set CA names for client cert request, function returns void */
4469 SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file));
4470 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004471 }
Emeric Brun850efd52014-01-29 12:24:34 +01004472 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004473 ha_alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
4474 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun850efd52014-01-29 12:24:34 +01004475 cfgerr++;
4476 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004477#ifdef X509_V_FLAG_CRL_CHECK
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004478 if (crl_file) {
Emeric Brund94b3fe2012-09-20 18:23:56 +02004479 X509_STORE *store = SSL_CTX_get_cert_store(ctx);
4480
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004481 if (!store || !X509_STORE_load_locations(store, crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004482 ha_alert("Proxy '%s': unable to configure CRL file '%s' for bind '%s' at [%s:%d].\n",
4483 curproxy->id, crl_file, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brund94b3fe2012-09-20 18:23:56 +02004484 cfgerr++;
4485 }
Emeric Brun561e5742012-10-02 15:20:55 +02004486 else {
4487 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4488 }
Emeric Brund94b3fe2012-09-20 18:23:56 +02004489 }
Emeric Brun051cdab2012-10-02 19:25:50 +02004490#endif
Emeric Brun644cde02012-12-14 11:21:13 +01004491 ERR_clear_error();
Emeric Brund94b3fe2012-09-20 18:23:56 +02004492 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004493#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
Nenad Merdanovic146defa2015-05-09 08:46:00 +02004494 if(bind_conf->keys_ref) {
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004495 if (!SSL_CTX_set_tlsext_ticket_key_cb(ctx, ssl_tlsext_ticket_key_cb)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004496 ha_alert("Proxy '%s': unable to set callback for TLS ticket validation for bind '%s' at [%s:%d].\n",
4497 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01004498 cfgerr++;
4499 }
4500 }
4501#endif
4502
William Lallemand4f45bb92017-10-30 20:08:51 +01004503 ssl_set_shctx(ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004504 conf_ciphers = (ssl_conf && ssl_conf->ciphers) ? ssl_conf->ciphers : bind_conf->ssl_conf.ciphers;
4505 if (conf_ciphers &&
4506 !SSL_CTX_set_cipher_list(ctx, conf_ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004507 ha_alert("Proxy '%s': unable to set SSL cipher list to '%s' for bind '%s' at [%s:%d].\n",
4508 curproxy->id, conf_ciphers, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brunfc0421f2012-09-07 17:30:07 +02004509 cfgerr++;
4510 }
4511
Emmanuel Hocdet839af572019-05-14 16:27:35 +02004512#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02004513 conf_ciphersuites = (ssl_conf && ssl_conf->ciphersuites) ? ssl_conf->ciphersuites : bind_conf->ssl_conf.ciphersuites;
4514 if (conf_ciphersuites &&
4515 !SSL_CTX_set_ciphersuites(ctx, conf_ciphersuites)) {
4516 ha_alert("Proxy '%s': unable to set TLS 1.3 cipher suites to '%s' for bind '%s' at [%s:%d].\n",
4517 curproxy->id, conf_ciphersuites, bind_conf->arg, bind_conf->file, bind_conf->line);
4518 cfgerr++;
4519 }
4520#endif
4521
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004522#ifndef OPENSSL_NO_DH
Remi Gacogne47783ef2015-05-29 15:53:22 +02004523 /* If tune.ssl.default-dh-param has not been set,
4524 neither has ssl-default-dh-file and no static DH
4525 params were in the certificate file. */
Willy Tarreauef934602016-12-22 23:12:01 +01004526 if (global_ssl.default_dh_param == 0 &&
Remi Gacogne47783ef2015-05-29 15:53:22 +02004527 global_dh == NULL &&
Remi Gacogne4f902b82015-05-28 16:23:00 +02004528 (ssl_dh_ptr_index == -1 ||
4529 SSL_CTX_get_ex_data(ctx, ssl_dh_ptr_index) == NULL)) {
Emmanuel Hocdetcc6c2a22017-03-03 17:04:14 +01004530 STACK_OF(SSL_CIPHER) * ciphers = NULL;
4531 const SSL_CIPHER * cipher = NULL;
4532 char cipher_description[128];
4533 /* The description of ciphers using an Ephemeral Diffie Hellman key exchange
4534 contains " Kx=DH " or " Kx=DH(". Beware of " Kx=DH/",
4535 which is not ephemeral DH. */
4536 const char dhe_description[] = " Kx=DH ";
4537 const char dhe_export_description[] = " Kx=DH(";
4538 int idx = 0;
4539 int dhe_found = 0;
4540 SSL *ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004541
Remi Gacogne23d5d372014-10-10 17:04:26 +02004542 ssl = SSL_new(ctx);
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004543
Remi Gacogne23d5d372014-10-10 17:04:26 +02004544 if (ssl) {
4545 ciphers = SSL_get_ciphers(ssl);
4546
4547 if (ciphers) {
4548 for (idx = 0; idx < sk_SSL_CIPHER_num(ciphers); idx++) {
4549 cipher = sk_SSL_CIPHER_value(ciphers, idx);
4550 if (SSL_CIPHER_description(cipher, cipher_description, sizeof (cipher_description)) == cipher_description) {
4551 if (strstr(cipher_description, dhe_description) != NULL ||
4552 strstr(cipher_description, dhe_export_description) != NULL) {
4553 dhe_found = 1;
4554 break;
4555 }
Remi Gacognec1eab8c2014-06-12 18:20:11 +02004556 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004557 }
4558 }
Remi Gacogne23d5d372014-10-10 17:04:26 +02004559 SSL_free(ssl);
4560 ssl = NULL;
Lukas Tribus90132722014-08-18 00:56:33 +02004561 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004562
Lukas Tribus90132722014-08-18 00:56:33 +02004563 if (dhe_found) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004564 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 +02004565 }
4566
Willy Tarreauef934602016-12-22 23:12:01 +01004567 global_ssl.default_dh_param = 1024;
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004568 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004569
Willy Tarreauef934602016-12-22 23:12:01 +01004570 if (global_ssl.default_dh_param >= 1024) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004571 if (local_dh_1024 == NULL) {
4572 local_dh_1024 = ssl_get_dh_1024();
4573 }
Willy Tarreauef934602016-12-22 23:12:01 +01004574 if (global_ssl.default_dh_param >= 2048) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004575 if (local_dh_2048 == NULL) {
4576 local_dh_2048 = ssl_get_dh_2048();
4577 }
Willy Tarreauef934602016-12-22 23:12:01 +01004578 if (global_ssl.default_dh_param >= 4096) {
Remi Gacogne8de54152014-07-15 11:36:40 +02004579 if (local_dh_4096 == NULL) {
4580 local_dh_4096 = ssl_get_dh_4096();
4581 }
Remi Gacogne8de54152014-07-15 11:36:40 +02004582 }
4583 }
4584 }
4585#endif /* OPENSSL_NO_DH */
Remi Gacognef46cd6e2014-06-12 14:58:40 +02004586
Emeric Brunfc0421f2012-09-07 17:30:07 +02004587 SSL_CTX_set_info_callback(ctx, ssl_sock_infocbk);
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004588#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
Emeric Brun29f037d2014-04-25 19:05:36 +02004589 SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
Willy Tarreau5cbe4ef2014-05-08 22:45:11 +02004590#endif
Emeric Brun29f037d2014-04-25 19:05:36 +02004591
Bernard Spil13c53f82018-02-15 13:34:58 +01004592#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004593 ssl_conf_cur = NULL;
4594 if (ssl_conf && ssl_conf->npn_str)
4595 ssl_conf_cur = ssl_conf;
4596 else if (bind_conf->ssl_conf.npn_str)
4597 ssl_conf_cur = &bind_conf->ssl_conf;
4598 if (ssl_conf_cur)
4599 SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_sock_advertise_npn_protos, ssl_conf_cur);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02004600#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01004601#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004602 ssl_conf_cur = NULL;
4603 if (ssl_conf && ssl_conf->alpn_str)
4604 ssl_conf_cur = ssl_conf;
4605 else if (bind_conf->ssl_conf.alpn_str)
4606 ssl_conf_cur = &bind_conf->ssl_conf;
4607 if (ssl_conf_cur)
4608 SSL_CTX_set_alpn_select_cb(ctx, ssl_sock_advertise_alpn_protos, ssl_conf_cur);
Willy Tarreauab861d32013-04-02 02:30:41 +02004609#endif
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004610#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004611 conf_curves = (ssl_conf && ssl_conf->curves) ? ssl_conf->curves : bind_conf->ssl_conf.curves;
4612 if (conf_curves) {
4613 if (!SSL_CTX_set1_curves_list(ctx, conf_curves)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004614 ha_alert("Proxy '%s': unable to set SSL curves list to '%s' for bind '%s' at [%s:%d].\n",
4615 curproxy->id, conf_curves, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004616 cfgerr++;
4617 }
Emmanuel Hocdeta52bb152017-03-20 11:11:49 +01004618#if defined(SSL_CTX_set_ecdh_auto)
4619 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
4620#endif
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004621 }
4622#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004623#if defined(SSL_CTX_set_tmp_ecdh) && !defined(OPENSSL_NO_ECDH)
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01004624 if (!conf_curves) {
Emeric Brun2b58d042012-09-20 17:10:03 +02004625 int i;
4626 EC_KEY *ecdh;
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004627#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004628 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
Olivier Houchardc2aae742017-09-22 18:26:28 +02004629 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4630 NULL);
4631
4632 if (ecdhe == NULL) {
4633 SSL_CTX_set_dh_auto(ctx, 1);
4634 return cfgerr;
4635 }
4636#else
4637 const char *ecdhe = (ssl_conf && ssl_conf->ecdhe) ? ssl_conf->ecdhe :
4638 (bind_conf->ssl_conf.ecdhe ? bind_conf->ssl_conf.ecdhe :
4639 ECDHE_DEFAULT_CURVE);
4640#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02004641
Emmanuel Hocdet98263292016-12-29 18:26:15 +01004642 i = OBJ_sn2nid(ecdhe);
Emeric Brun2b58d042012-09-20 17:10:03 +02004643 if (!i || ((ecdh = EC_KEY_new_by_curve_name(i)) == NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004644 ha_alert("Proxy '%s': unable to set elliptic named curve to '%s' for bind '%s' at [%s:%d].\n",
4645 curproxy->id, ecdhe, bind_conf->arg, bind_conf->file, bind_conf->line);
Emeric Brun2b58d042012-09-20 17:10:03 +02004646 cfgerr++;
4647 }
4648 else {
4649 SSL_CTX_set_tmp_ecdh(ctx, ecdh);
4650 EC_KEY_free(ecdh);
4651 }
4652 }
4653#endif
4654
Emeric Brunfc0421f2012-09-07 17:30:07 +02004655 return cfgerr;
4656}
4657
Evan Broderbe554312013-06-27 00:05:25 -07004658static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
4659{
4660 const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
4661 size_t prefixlen, suffixlen;
4662
4663 /* Trivial case */
4664 if (strcmp(pattern, hostname) == 0)
4665 return 1;
4666
Evan Broderbe554312013-06-27 00:05:25 -07004667 /* The rest of this logic is based on RFC 6125, section 6.4.3
4668 * (http://tools.ietf.org/html/rfc6125#section-6.4.3) */
4669
Emeric Bruna848dae2013-10-08 11:27:28 +02004670 pattern_wildcard = NULL;
4671 pattern_left_label_end = pattern;
4672 while (*pattern_left_label_end != '.') {
4673 switch (*pattern_left_label_end) {
4674 case 0:
4675 /* End of label not found */
4676 return 0;
4677 case '*':
4678 /* If there is more than one wildcards */
4679 if (pattern_wildcard)
4680 return 0;
4681 pattern_wildcard = pattern_left_label_end;
4682 break;
4683 }
4684 pattern_left_label_end++;
4685 }
4686
4687 /* If it's not trivial and there is no wildcard, it can't
4688 * match */
4689 if (!pattern_wildcard)
Evan Broderbe554312013-06-27 00:05:25 -07004690 return 0;
4691
4692 /* Make sure all labels match except the leftmost */
4693 hostname_left_label_end = strchr(hostname, '.');
4694 if (!hostname_left_label_end
4695 || strcmp(pattern_left_label_end, hostname_left_label_end) != 0)
4696 return 0;
4697
4698 /* Make sure the leftmost label of the hostname is long enough
4699 * that the wildcard can match */
Emeric Brun369da852013-10-08 11:39:35 +02004700 if (hostname_left_label_end - hostname < (pattern_left_label_end - pattern) - 1)
Evan Broderbe554312013-06-27 00:05:25 -07004701 return 0;
4702
4703 /* Finally compare the string on either side of the
4704 * wildcard */
4705 prefixlen = pattern_wildcard - pattern;
4706 suffixlen = pattern_left_label_end - (pattern_wildcard + 1);
Emeric Bruna848dae2013-10-08 11:27:28 +02004707 if ((prefixlen && (memcmp(pattern, hostname, prefixlen) != 0))
4708 || (suffixlen && (memcmp(pattern_wildcard + 1, hostname_left_label_end - suffixlen, suffixlen) != 0)))
Evan Broderbe554312013-06-27 00:05:25 -07004709 return 0;
4710
4711 return 1;
4712}
4713
4714static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
4715{
4716 SSL *ssl;
4717 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01004718 struct ssl_sock_ctx *ssl_ctx;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004719 const char *servername;
Willy Tarreau71d058c2017-07-26 20:09:56 +02004720 const char *sni;
Evan Broderbe554312013-06-27 00:05:25 -07004721
4722 int depth;
4723 X509 *cert;
4724 STACK_OF(GENERAL_NAME) *alt_names;
4725 int i;
4726 X509_NAME *cert_subject;
4727 char *str;
4728
4729 if (ok == 0)
4730 return ok;
4731
4732 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
Thierry FOURNIER28962c92018-06-17 21:37:05 +02004733 conn = SSL_get_ex_data(ssl, ssl_app_data_index);
Olivier Houchard66ab4982019-02-26 18:37:15 +01004734 ssl_ctx = conn->xprt_ctx;
Evan Broderbe554312013-06-27 00:05:25 -07004735
Willy Tarreauad92a9a2017-07-28 11:38:41 +02004736 /* We're checking if the provided hostnames match the desired one. The
4737 * desired hostname comes from the SNI we presented if any, or if not
4738 * provided then it may have been explicitly stated using a "verifyhost"
4739 * directive. If neither is set, we don't care about the name so the
4740 * verification is OK.
Willy Tarreau2ab88672017-07-05 18:23:03 +02004741 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01004742 servername = SSL_get_servername(ssl_ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau71d058c2017-07-26 20:09:56 +02004743 sni = servername;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004744 if (!servername) {
Willy Tarreau07d94e42018-09-20 10:57:52 +02004745 servername = __objt_server(conn->target)->ssl_ctx.verify_host;
Willy Tarreau2ab88672017-07-05 18:23:03 +02004746 if (!servername)
4747 return ok;
4748 }
Evan Broderbe554312013-06-27 00:05:25 -07004749
4750 /* We only need to verify the CN on the actual server cert,
4751 * not the indirect CAs */
4752 depth = X509_STORE_CTX_get_error_depth(ctx);
4753 if (depth != 0)
4754 return ok;
4755
4756 /* At this point, the cert is *not* OK unless we can find a
4757 * hostname match */
4758 ok = 0;
4759
4760 cert = X509_STORE_CTX_get_current_cert(ctx);
4761 /* It seems like this might happen if verify peer isn't set */
4762 if (!cert)
4763 return ok;
4764
4765 alt_names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
4766 if (alt_names) {
4767 for (i = 0; !ok && i < sk_GENERAL_NAME_num(alt_names); i++) {
4768 GENERAL_NAME *name = sk_GENERAL_NAME_value(alt_names, i);
4769 if (name->type == GEN_DNS) {
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004770#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Emeric Bruna33410c2013-09-17 15:47:48 +02004771 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.ia5) >= 0) {
4772#else
Evan Broderbe554312013-06-27 00:05:25 -07004773 if (ASN1_STRING_to_UTF8((unsigned char **)&str, name->d.dNSName) >= 0) {
Emeric Bruna33410c2013-09-17 15:47:48 +02004774#endif
Evan Broderbe554312013-06-27 00:05:25 -07004775 ok = ssl_sock_srv_hostcheck(str, servername);
4776 OPENSSL_free(str);
4777 }
4778 }
4779 }
Emeric Brun4ad50a42013-09-17 15:19:54 +02004780 sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free);
Evan Broderbe554312013-06-27 00:05:25 -07004781 }
4782
4783 cert_subject = X509_get_subject_name(cert);
4784 i = -1;
4785 while (!ok && (i = X509_NAME_get_index_by_NID(cert_subject, NID_commonName, i)) != -1) {
4786 X509_NAME_ENTRY *entry = X509_NAME_get_entry(cert_subject, i);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02004787 ASN1_STRING *value;
4788 value = X509_NAME_ENTRY_get_data(entry);
4789 if (ASN1_STRING_to_UTF8((unsigned char **)&str, value) >= 0) {
Evan Broderbe554312013-06-27 00:05:25 -07004790 ok = ssl_sock_srv_hostcheck(str, servername);
4791 OPENSSL_free(str);
4792 }
4793 }
4794
Willy Tarreau71d058c2017-07-26 20:09:56 +02004795 /* report the mismatch and indicate if SNI was used or not */
4796 if (!ok && !conn->err_code)
4797 conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
Evan Broderbe554312013-06-27 00:05:25 -07004798 return ok;
4799}
4800
Emeric Brun94324a42012-10-11 14:00:19 +02004801/* prepare ssl context from servers options. Returns an error count */
Willy Tarreau03209342016-12-22 17:08:28 +01004802int ssl_sock_prepare_srv_ctx(struct server *srv)
Emeric Brun94324a42012-10-11 14:00:19 +02004803{
Willy Tarreau03209342016-12-22 17:08:28 +01004804 struct proxy *curproxy = srv->proxy;
Emeric Brun94324a42012-10-11 14:00:19 +02004805 int cfgerr = 0;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004806 long options =
Emeric Brun94324a42012-10-11 14:00:19 +02004807 SSL_OP_ALL | /* all known workarounds for bugs */
4808 SSL_OP_NO_SSLv2 |
4809 SSL_OP_NO_COMPRESSION;
Remi Gacogneaf5c3da2014-05-19 10:29:58 +02004810 long mode =
Emeric Brun94324a42012-10-11 14:00:19 +02004811 SSL_MODE_ENABLE_PARTIAL_WRITE |
4812 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
Willy Tarreau396a1862014-11-13 14:06:52 +01004813 SSL_MODE_RELEASE_BUFFERS |
4814 SSL_MODE_SMALL_BUFFERS;
Emeric Brun850efd52014-01-29 12:24:34 +01004815 int verify = SSL_VERIFY_NONE;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004816 SSL_CTX *ctx = NULL;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004817 struct tls_version_filter *conf_ssl_methods = &srv->ssl_ctx.methods;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004818 int i, min, max, hole;
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004819 int flags = MC_SSL_O_ALL;
Emeric Brun94324a42012-10-11 14:00:19 +02004820
Thierry Fournier383085f2013-01-24 14:15:43 +01004821 /* Make sure openssl opens /dev/urandom before the chroot */
4822 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004823 ha_alert("OpenSSL random data generator initialization failed.\n");
Thierry Fournier383085f2013-01-24 14:15:43 +01004824 cfgerr++;
4825 }
4826
Willy Tarreaufce03112015-01-15 21:32:40 +01004827 /* Automatic memory computations need to know we use SSL there */
4828 global.ssl_used_backend = 1;
4829
4830 /* Initiate SSL context for current server */
Emeric Brun821bb9b2017-06-15 16:37:39 +02004831 if (!srv->ssl_ctx.reused_sess) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01004832 if ((srv->ssl_ctx.reused_sess = calloc(1, global.nbthread*sizeof(*srv->ssl_ctx.reused_sess))) == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004833 ha_alert("Proxy '%s', server '%s' [%s:%d] out of memory.\n",
4834 curproxy->id, srv->id,
4835 srv->conf.file, srv->conf.line);
Emeric Brun821bb9b2017-06-15 16:37:39 +02004836 cfgerr++;
4837 return cfgerr;
4838 }
4839 }
Emeric Brun94324a42012-10-11 14:00:19 +02004840 if (srv->use_ssl)
4841 srv->xprt = &ssl_sock;
4842 if (srv->check.use_ssl)
Cyril Bonté9ce13112014-11-15 22:41:27 +01004843 srv->check.xprt = &ssl_sock;
Emeric Brun94324a42012-10-11 14:00:19 +02004844
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004845 ctx = SSL_CTX_new(SSLv23_client_method());
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004846 if (!ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004847 ha_alert("config : %s '%s', server '%s': unable to allocate ssl context.\n",
4848 proxy_type_str(curproxy), curproxy->id,
4849 srv->id);
Emeric Brun94324a42012-10-11 14:00:19 +02004850 cfgerr++;
4851 return cfgerr;
4852 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004853
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004854 if (conf_ssl_methods->flags && (conf_ssl_methods->min || conf_ssl_methods->max))
Christopher Faulet767a84b2017-11-24 16:50:31 +01004855 ha_warning("config : %s '%s': no-sslv3/no-tlsv1x are ignored for server '%s'. "
4856 "Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4857 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004858 else
4859 flags = conf_ssl_methods->flags;
4860
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004861 /* Real min and max should be determinate with configuration and openssl's capabilities */
4862 if (conf_ssl_methods->min)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004863 flags |= (methodVersions[conf_ssl_methods->min].flag - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004864 if (conf_ssl_methods->max)
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004865 flags |= ~((methodVersions[conf_ssl_methods->max].flag << 1) - 1);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004866
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004867 /* find min, max and holes */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004868 min = max = CONF_TLSV_NONE;
4869 hole = 0;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004870 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004871 /* version is in openssl && version not disable in configuration */
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004872 if (methodVersions[i].option && !(flags & methodVersions[i].flag)) {
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004873 if (min) {
4874 if (hole) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004875 ha_warning("config : %s '%s': SSL/TLS versions range not contiguous for server '%s'. "
4876 "Hole find for %s. Use only 'ssl-min-ver' and 'ssl-max-ver' to fix.\n",
4877 proxy_type_str(curproxy), curproxy->id, srv->id,
4878 methodVersions[hole].name);
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004879 hole = 0;
4880 }
4881 max = i;
4882 }
4883 else {
4884 min = max = i;
4885 }
4886 }
4887 else {
4888 if (min)
4889 hole = i;
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004890 }
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004891 if (!min) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004892 ha_alert("config : %s '%s': all SSL/TLS versions are disabled for server '%s'.\n",
4893 proxy_type_str(curproxy), curproxy->id, srv->id);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004894 cfgerr += 1;
4895 }
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004896
Willy Tarreau9a1ab082019-05-09 13:26:41 +02004897#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004898 /* Keep force-xxx implementation as it is in older haproxy. It's a
Joseph Herlant017b3da2018-11-15 09:07:59 -08004899 precautionary measure to avoid any surprise with older openssl version. */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004900 if (min == max)
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004901 methodVersions[min].ctx_set_version(ctx, SET_CLIENT);
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02004902 else
4903 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
4904 if (flags & methodVersions[i].flag)
4905 options |= methodVersions[i].option;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004906#else /* openssl >= 1.1.0 */
Emmanuel Hocdetb4e9ba42017-03-30 19:25:07 +02004907 /* set the max_version is required to cap TLS version or activate new TLS (v1.3) */
Emmanuel Hocdet4aa615f2017-05-18 12:33:19 +02004908 methodVersions[min].ctx_set_version(ctx, SET_MIN);
4909 methodVersions[max].ctx_set_version(ctx, SET_MAX);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02004910#endif
4911
4912 if (srv->ssl_ctx.options & SRV_SSL_O_NO_TLS_TICKETS)
4913 options |= SSL_OP_NO_TICKET;
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004914 SSL_CTX_set_options(ctx, options);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004915
Willy Tarreau5db847a2019-05-09 14:13:35 +02004916#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00004917 if (global_ssl.async)
4918 mode |= SSL_MODE_ASYNC;
4919#endif
Emmanuel Hocdet4de1ff12017-03-03 12:21:32 +01004920 SSL_CTX_set_mode(ctx, mode);
4921 srv->ssl_ctx.ctx = ctx;
4922
Emeric Bruna7aa3092012-10-26 12:58:00 +02004923 if (srv->ssl_ctx.client_crt) {
4924 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 +01004925 ha_alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
4926 proxy_type_str(curproxy), curproxy->id,
4927 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004928 cfgerr++;
4929 }
4930 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 +01004931 ha_alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n",
4932 proxy_type_str(curproxy), curproxy->id,
4933 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004934 cfgerr++;
4935 }
4936 else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004937 ha_alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n",
4938 proxy_type_str(curproxy), curproxy->id,
4939 srv->id, srv->ssl_ctx.client_crt);
Emeric Bruna7aa3092012-10-26 12:58:00 +02004940 cfgerr++;
4941 }
4942 }
Emeric Brun94324a42012-10-11 14:00:19 +02004943
Emeric Brun850efd52014-01-29 12:24:34 +01004944 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
4945 verify = SSL_VERIFY_PEER;
Emeric Brun850efd52014-01-29 12:24:34 +01004946 switch (srv->ssl_ctx.verify) {
4947 case SSL_SOCK_VERIFY_NONE:
4948 verify = SSL_VERIFY_NONE;
4949 break;
4950 case SSL_SOCK_VERIFY_REQUIRED:
4951 verify = SSL_VERIFY_PEER;
4952 break;
4953 }
Evan Broderbe554312013-06-27 00:05:25 -07004954 SSL_CTX_set_verify(srv->ssl_ctx.ctx,
Emeric Brun850efd52014-01-29 12:24:34 +01004955 verify,
Willy Tarreau2ab88672017-07-05 18:23:03 +02004956 (srv->ssl_ctx.verify_host || (verify & SSL_VERIFY_PEER)) ? ssl_sock_srv_verifycbk : NULL);
Emeric Brun850efd52014-01-29 12:24:34 +01004957 if (verify & SSL_VERIFY_PEER) {
Emeric Brunef42d922012-10-11 16:11:36 +02004958 if (srv->ssl_ctx.ca_file) {
4959 /* load CAfile to verify */
4960 if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004961 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to load CA file '%s'.\n",
4962 curproxy->id, srv->id,
4963 srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004964 cfgerr++;
4965 }
4966 }
Emeric Brun850efd52014-01-29 12:24:34 +01004967 else {
4968 if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
Christopher Faulet767a84b2017-11-24 16:50:31 +01004969 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",
4970 curproxy->id, srv->id,
4971 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004972 else
Christopher Faulet767a84b2017-11-24 16:50:31 +01004973 ha_alert("Proxy '%s', server '%s' [%s:%d] verify is enabled but no CA file specified.\n",
4974 curproxy->id, srv->id,
4975 srv->conf.file, srv->conf.line);
Emeric Brun850efd52014-01-29 12:24:34 +01004976 cfgerr++;
4977 }
Emeric Brunef42d922012-10-11 16:11:36 +02004978#ifdef X509_V_FLAG_CRL_CHECK
4979 if (srv->ssl_ctx.crl_file) {
4980 X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
4981
4982 if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01004983 ha_alert("Proxy '%s', server '%s' [%s:%d] unable to configure CRL file '%s'.\n",
4984 curproxy->id, srv->id,
4985 srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
Emeric Brunef42d922012-10-11 16:11:36 +02004986 cfgerr++;
4987 }
4988 else {
4989 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
4990 }
4991 }
4992#endif
4993 }
4994
Olivier Houchardbd84ac82017-11-03 13:43:35 +01004995 SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_CLIENT |
4996 SSL_SESS_CACHE_NO_INTERNAL_STORE);
4997 SSL_CTX_sess_set_new_cb(srv->ssl_ctx.ctx, ssl_sess_new_srv_cb);
Emeric Brun94324a42012-10-11 14:00:19 +02004998 if (srv->ssl_ctx.ciphers &&
4999 !SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005000 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set SSL cipher list to '%s'.\n",
5001 curproxy->id, srv->id,
5002 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphers);
Emeric Brun94324a42012-10-11 14:00:19 +02005003 cfgerr++;
5004 }
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005005
Emmanuel Hocdet839af572019-05-14 16:27:35 +02005006#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005007 if (srv->ssl_ctx.ciphersuites &&
Pierre Cheynierbc34cd12019-03-21 16:15:47 +00005008 !SSL_CTX_set_ciphersuites(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphersuites)) {
Dirkjan Bussink415150f2018-09-14 11:14:21 +02005009 ha_alert("Proxy '%s', server '%s' [%s:%d] : unable to set TLS 1.3 cipher suites to '%s'.\n",
5010 curproxy->id, srv->id,
5011 srv->conf.file, srv->conf.line, srv->ssl_ctx.ciphersuites);
5012 cfgerr++;
5013 }
5014#endif
Olivier Houchardc7566002018-11-20 23:33:50 +01005015#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
5016 if (srv->ssl_ctx.npn_str)
5017 SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, srv);
5018#endif
5019#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5020 if (srv->ssl_ctx.alpn_str)
5021 SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
5022#endif
5023
Emeric Brun94324a42012-10-11 14:00:19 +02005024
5025 return cfgerr;
5026}
5027
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005028/* Walks down the two trees in bind_conf and prepares all certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005029 * be NULL, in which case nothing is done. Returns the number of errors
5030 * encountered.
5031 */
Willy Tarreau03209342016-12-22 17:08:28 +01005032int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005033{
5034 struct ebmb_node *node;
5035 struct sni_ctx *sni;
5036 int err = 0;
5037
Willy Tarreaufce03112015-01-15 21:32:40 +01005038 /* Automatic memory computations need to know we use SSL there */
5039 global.ssl_used_frontend = 1;
5040
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005041 /* Make sure openssl opens /dev/urandom before the chroot */
5042 if (!ssl_initialize_random()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005043 ha_alert("OpenSSL random data generator initialization failed.\n");
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005044 err++;
5045 }
5046 /* Create initial_ctx used to start the ssl connection before do switchctx */
5047 if (!bind_conf->initial_ctx) {
Emmanuel Hocdetabd32332017-05-05 18:06:12 +02005048 err += ssl_sock_initial_ctx(bind_conf);
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005049 /* It should not be necessary to call this function, but it's
5050 necessary first to check and move all initialisation related
5051 to initial_ctx in ssl_sock_initial_ctx. */
5052 err += ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx);
5053 }
Emeric Brun0bed9942014-10-30 19:25:24 +01005054 if (bind_conf->default_ctx)
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005055 err += ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx);
Emeric Brun0bed9942014-10-30 19:25:24 +01005056
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005057 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005058 while (node) {
5059 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005060 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5061 /* only initialize the CTX on its first occurrence and
5062 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005063 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005064 node = ebmb_next(node);
5065 }
5066
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005067 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005068 while (node) {
5069 sni = ebmb_entry(node, struct sni_ctx, name);
Emeric Brun0bed9942014-10-30 19:25:24 +01005070 if (!sni->order && sni->ctx != bind_conf->default_ctx)
5071 /* only initialize the CTX on its first occurrence and
5072 if it is not the default_ctx */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005073 err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005074 node = ebmb_next(node);
5075 }
5076 return err;
5077}
5078
Willy Tarreau55d37912016-12-21 23:38:39 +01005079/* Prepares all the contexts for a bind_conf and allocates the shared SSL
5080 * context if needed. Returns < 0 on error, 0 on success. The warnings and
5081 * alerts are directly emitted since the rest of the stack does it below.
5082 */
5083int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
5084{
5085 struct proxy *px = bind_conf->frontend;
5086 int alloc_ctx;
5087 int err;
5088
5089 if (!bind_conf->is_ssl) {
5090 if (bind_conf->default_ctx) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005091 ha_warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
5092 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreau55d37912016-12-21 23:38:39 +01005093 }
5094 return 0;
5095 }
5096 if (!bind_conf->default_ctx) {
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005097 if (bind_conf->strict_sni && !bind_conf->generate_certs) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005098 ha_warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d], ssl connections will fail (use 'crt').\n",
5099 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005100 }
5101 else {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005102 ha_alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
5103 px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Emmanuel Hocdetaa0d6372017-08-09 11:24:25 +02005104 return -1;
5105 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005106 }
William Lallemandc61c0b32017-12-04 18:46:39 +01005107 if (!ssl_shctx && global.tune.sslcachesize) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005108 alloc_ctx = shctx_init(&ssl_shctx, global.tune.sslcachesize,
Frédéric Lécailleb7838af2018-10-22 16:21:39 +02005109 sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE, -1,
William Lallemandc3cd35f2017-11-28 11:04:43 +01005110 sizeof(*sh_ssl_sess_tree),
5111 ((global.nbthread > 1) || (!global_ssl.private_cache && (global.nbproc > 1))) ? 1 : 0);
Frédéric Lécaille4c8aa112018-10-25 20:22:46 +02005112 if (alloc_ctx <= 0) {
William Lallemandc3cd35f2017-11-28 11:04:43 +01005113 if (alloc_ctx == SHCTX_E_INIT_LOCK)
5114 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");
5115 else
5116 ha_alert("Unable to allocate SSL session cache.\n");
5117 return -1;
5118 }
5119 /* free block callback */
5120 ssl_shctx->free_block = sh_ssl_sess_free_blocks;
5121 /* init the root tree within the extra space */
5122 sh_ssl_sess_tree = (void *)ssl_shctx + sizeof(struct shared_context);
5123 *sh_ssl_sess_tree = EB_ROOT_UNIQUE;
Willy Tarreau55d37912016-12-21 23:38:39 +01005124 }
Willy Tarreau55d37912016-12-21 23:38:39 +01005125 err = 0;
5126 /* initialize all certificate contexts */
5127 err += ssl_sock_prepare_all_ctx(bind_conf);
5128
5129 /* initialize CA variables if the certificates generation is enabled */
5130 err += ssl_sock_load_ca(bind_conf);
5131
5132 return -err;
5133}
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005134
5135/* release ssl context allocated for servers. */
5136void ssl_sock_free_srv_ctx(struct server *srv)
5137{
Olivier Houchardc7566002018-11-20 23:33:50 +01005138#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
5139 if (srv->ssl_ctx.alpn_str)
5140 free(srv->ssl_ctx.alpn_str);
5141#endif
Lukas Tribusda95fd92018-11-25 13:21:27 +01005142#ifdef OPENSSL_NPN_NEGOTIATED
Olivier Houchardc7566002018-11-20 23:33:50 +01005143 if (srv->ssl_ctx.npn_str)
5144 free(srv->ssl_ctx.npn_str);
Lukas Tribus7706b852018-11-26 22:57:17 +01005145#endif
Christopher Faulet77fe80c2015-07-29 13:02:40 +02005146 if (srv->ssl_ctx.ctx)
5147 SSL_CTX_free(srv->ssl_ctx.ctx);
5148}
5149
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005150/* Walks down the two trees in bind_conf and frees all the certs. The pointer may
Emeric Brunfc0421f2012-09-07 17:30:07 +02005151 * be NULL, in which case nothing is done. The default_ctx is nullified too.
5152 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005153void ssl_sock_free_all_ctx(struct bind_conf *bind_conf)
Emeric Brunfc0421f2012-09-07 17:30:07 +02005154{
5155 struct ebmb_node *node, *back;
5156 struct sni_ctx *sni;
5157
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005158 node = ebmb_first(&bind_conf->sni_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005159 while (node) {
5160 sni = ebmb_entry(node, struct sni_ctx, name);
5161 back = ebmb_next(node);
5162 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005163 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005164 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005165 ssl_sock_free_ssl_conf(sni->conf);
5166 free(sni->conf);
5167 sni->conf = NULL;
5168 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005169 free(sni);
5170 node = back;
5171 }
5172
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005173 node = ebmb_first(&bind_conf->sni_w_ctx);
Emeric Brunfc0421f2012-09-07 17:30:07 +02005174 while (node) {
5175 sni = ebmb_entry(node, struct sni_ctx, name);
5176 back = ebmb_next(node);
5177 ebmb_delete(node);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005178 if (!sni->order) { /* only free the CTX on its first occurrence */
Emeric Brunfc0421f2012-09-07 17:30:07 +02005179 SSL_CTX_free(sni->ctx);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005180 ssl_sock_free_ssl_conf(sni->conf);
5181 free(sni->conf);
5182 sni->conf = NULL;
5183 }
Emeric Brunfc0421f2012-09-07 17:30:07 +02005184 free(sni);
5185 node = back;
5186 }
Emmanuel Hocdetf6b37c62017-03-06 15:34:44 +01005187 SSL_CTX_free(bind_conf->initial_ctx);
5188 bind_conf->initial_ctx = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005189 bind_conf->default_ctx = NULL;
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005190 bind_conf->default_ssl_conf = NULL;
Emeric Brune1f38db2012-09-03 20:36:47 +02005191}
5192
Willy Tarreau795cdab2016-12-22 17:30:54 +01005193/* Destroys all the contexts for a bind_conf. This is used during deinit(). */
5194void ssl_sock_destroy_bind_conf(struct bind_conf *bind_conf)
5195{
5196 ssl_sock_free_ca(bind_conf);
5197 ssl_sock_free_all_ctx(bind_conf);
Emmanuel Hocdet98263292016-12-29 18:26:15 +01005198 ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
Willy Tarreau795cdab2016-12-22 17:30:54 +01005199 free(bind_conf->ca_sign_file);
5200 free(bind_conf->ca_sign_pass);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02005201 if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01005202 free(bind_conf->keys_ref->filename);
5203 free(bind_conf->keys_ref->tlskeys);
5204 LIST_DEL(&bind_conf->keys_ref->list);
5205 free(bind_conf->keys_ref);
5206 }
5207 bind_conf->keys_ref = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005208 bind_conf->ca_sign_pass = NULL;
5209 bind_conf->ca_sign_file = NULL;
Willy Tarreau795cdab2016-12-22 17:30:54 +01005210}
5211
Christopher Faulet31af49d2015-06-09 17:29:50 +02005212/* Load CA cert file and private key used to generate certificates */
5213int
Willy Tarreau03209342016-12-22 17:08:28 +01005214ssl_sock_load_ca(struct bind_conf *bind_conf)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005215{
Willy Tarreau03209342016-12-22 17:08:28 +01005216 struct proxy *px = bind_conf->frontend;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005217 FILE *fp;
5218 X509 *cacert = NULL;
5219 EVP_PKEY *capkey = NULL;
5220 int err = 0;
5221
Christopher Fauletf8bb0ce2017-09-15 09:52:49 +02005222 if (!bind_conf->generate_certs)
Christopher Faulet31af49d2015-06-09 17:29:50 +02005223 return err;
5224
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005225#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +02005226 if (global_ssl.ctx_cache) {
Willy Tarreauef934602016-12-22 23:12:01 +01005227 ssl_ctx_lru_tree = lru64_new(global_ssl.ctx_cache);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005228 }
Christopher Fauletd2cab922015-07-28 16:03:47 +02005229 ssl_ctx_lru_seed = (unsigned int)time(NULL);
Emeric Brun821bb9b2017-06-15 16:37:39 +02005230 ssl_ctx_serial = now_ms;
Willy Tarreaua84c2672015-10-09 12:10:13 +02005231#endif
Christopher Fauletd2cab922015-07-28 16:03:47 +02005232
Christopher Faulet31af49d2015-06-09 17:29:50 +02005233 if (!bind_conf->ca_sign_file) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005234 ha_alert("Proxy '%s': cannot enable certificate generation, "
5235 "no CA certificate File configured at [%s:%d].\n",
5236 px->id, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005237 goto load_error;
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005238 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005239
5240 /* read in the CA certificate */
5241 if (!(fp = fopen(bind_conf->ca_sign_file, "r"))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005242 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5243 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005244 goto load_error;
5245 }
5246 if (!(cacert = PEM_read_X509(fp, NULL, NULL, NULL))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005247 ha_alert("Proxy '%s': Failed to read CA certificate file '%s' at [%s:%d].\n",
5248 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005249 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005250 }
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005251 rewind(fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005252 if (!(capkey = PEM_read_PrivateKey(fp, NULL, NULL, bind_conf->ca_sign_pass))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01005253 ha_alert("Proxy '%s': Failed to read CA private key file '%s' at [%s:%d].\n",
5254 px->id, bind_conf->ca_sign_file, bind_conf->file, bind_conf->line);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005255 goto read_error;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005256 }
Christopher Faulet31af49d2015-06-09 17:29:50 +02005257
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005258 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005259 bind_conf->ca_sign_cert = cacert;
5260 bind_conf->ca_sign_pkey = capkey;
5261 return err;
5262
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005263 read_error:
5264 fclose (fp);
Christopher Faulet31af49d2015-06-09 17:29:50 +02005265 if (capkey) EVP_PKEY_free(capkey);
5266 if (cacert) X509_free(cacert);
Christopher Fauletc6f02fb2015-10-09 10:53:31 +02005267 load_error:
5268 bind_conf->generate_certs = 0;
5269 err++;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005270 return err;
5271}
5272
5273/* Release CA cert and private key used to generate certificated */
5274void
5275ssl_sock_free_ca(struct bind_conf *bind_conf)
5276{
Christopher Faulet31af49d2015-06-09 17:29:50 +02005277 if (bind_conf->ca_sign_pkey)
5278 EVP_PKEY_free(bind_conf->ca_sign_pkey);
5279 if (bind_conf->ca_sign_cert)
5280 X509_free(bind_conf->ca_sign_cert);
Willy Tarreau94ff03a2016-12-22 17:57:46 +01005281 bind_conf->ca_sign_pkey = NULL;
5282 bind_conf->ca_sign_cert = NULL;
Christopher Faulet31af49d2015-06-09 17:29:50 +02005283}
5284
Emeric Brun46591952012-05-18 15:47:34 +02005285/*
5286 * This function is called if SSL * context is not yet allocated. The function
5287 * is designed to be called before any other data-layer operation and sets the
5288 * handshake flag on the connection. It is safe to call it multiple times.
5289 * It returns 0 on success and -1 in error case.
5290 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005291static int ssl_sock_init(struct connection *conn, void **xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005292{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005293 struct ssl_sock_ctx *ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005294 /* already initialized */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005295 if (*xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005296 return 0;
5297
Willy Tarreau3c728722014-01-23 13:50:42 +01005298 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005299 return 0;
5300
Olivier Houchard66ab4982019-02-26 18:37:15 +01005301 ctx = pool_alloc(ssl_sock_ctx_pool);
5302 if (!ctx) {
5303 conn->err_code = CO_ER_SSL_NO_MEM;
5304 return -1;
5305 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005306 ctx->wait_event.tasklet = tasklet_new();
5307 if (!ctx->wait_event.tasklet) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005308 conn->err_code = CO_ER_SSL_NO_MEM;
5309 pool_free(ssl_sock_ctx_pool, ctx);
5310 return -1;
5311 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005312 ctx->wait_event.tasklet->process = ssl_sock_io_cb;
5313 ctx->wait_event.tasklet->context = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005314 ctx->wait_event.events = 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005315 ctx->sent_early_data = 0;
5316 ctx->tmp_early_data = -1;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005317 ctx->conn = conn;
Olivier Houchard81284e62019-06-06 13:21:23 +02005318 ctx->send_wait = NULL;
5319 ctx->recv_wait = NULL;
Emeric Brun5762a0d2019-09-06 15:36:02 +02005320 ctx->xprt_st = 0;
5321 ctx->xprt_ctx = NULL;
Olivier Houcharda8955d52019-04-07 22:00:38 +02005322
5323 /* Only work with sockets for now, this should be adapted when we'll
5324 * add QUIC support.
5325 */
5326 ctx->xprt = xprt_get(XPRT_RAW);
Olivier Houchard19afb272019-05-23 18:24:07 +02005327 if (ctx->xprt->init) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005328 if (ctx->xprt->init(conn, &ctx->xprt_ctx) != 0)
5329 goto err;
Olivier Houchard19afb272019-05-23 18:24:07 +02005330 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005331
Willy Tarreau20879a02012-12-03 16:32:10 +01005332 if (global.maxsslconn && sslconns >= global.maxsslconn) {
5333 conn->err_code = CO_ER_SSL_TOO_MANY;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005334 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005335 }
Willy Tarreau403edff2012-09-06 11:58:37 +02005336
Emeric Brun46591952012-05-18 15:47:34 +02005337 /* If it is in client mode initiate SSL session
5338 in connect state otherwise accept state */
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005339 if (objt_server(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005340 int may_retry = 1;
5341
5342 retry_connect:
Emeric Brun46591952012-05-18 15:47:34 +02005343 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005344 ctx->ssl = SSL_new(__objt_server(conn->target)->ssl_ctx.ctx);
5345 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005346 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005347 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005348 goto retry_connect;
5349 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005350 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005351 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005352 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005353 ctx->bio = BIO_new(ha_meth);
5354 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005355 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005356 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005357 goto retry_connect;
5358 }
Emeric Brun55476152014-11-12 17:35:37 +01005359 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005360 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005361 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005362 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005363 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005364
Evan Broderbe554312013-06-27 00:05:25 -07005365 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005366 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5367 SSL_free(ctx->ssl);
5368 ctx->ssl = NULL;
Emeric Brun55476152014-11-12 17:35:37 +01005369 conn->xprt_ctx = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005370 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005371 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005372 goto retry_connect;
5373 }
Emeric Brun55476152014-11-12 17:35:37 +01005374 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005375 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005376 }
5377
Olivier Houchard66ab4982019-02-26 18:37:15 +01005378 SSL_set_connect_state(ctx->ssl);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005379 if (__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5380 const unsigned char *ptr = __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr;
5381 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 +01005382 if (sess && !SSL_set_session(ctx->ssl, sess)) {
Olivier Houcharde6060c52017-11-16 17:42:52 +01005383 SSL_SESSION_free(sess);
Willy Tarreau07d94e42018-09-20 10:57:52 +02005384 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5385 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Olivier Houcharde6060c52017-11-16 17:42:52 +01005386 } else if (sess) {
5387 SSL_SESSION_free(sess);
Emeric Brun55476152014-11-12 17:35:37 +01005388 }
5389 }
Evan Broderbe554312013-06-27 00:05:25 -07005390
Emeric Brun46591952012-05-18 15:47:34 +02005391 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005392 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Willy Tarreau403edff2012-09-06 11:58:37 +02005393
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005394 _HA_ATOMIC_ADD(&sslconns, 1);
5395 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005396 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005397 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005398 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005399 if (conn->flags & CO_FL_ERROR)
5400 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005401 return 0;
5402 }
Willy Tarreau3fdb3662012-11-12 00:42:33 +01005403 else if (objt_listener(conn->target)) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005404 int may_retry = 1;
5405
5406 retry_accept:
Emeric Brun46591952012-05-18 15:47:34 +02005407 /* Alloc a new SSL session ctx */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005408 ctx->ssl = SSL_new(__objt_listener(conn->target)->bind_conf->initial_ctx);
5409 if (!ctx->ssl) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005410 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005411 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005412 goto retry_accept;
5413 }
Willy Tarreau20879a02012-12-03 16:32:10 +01005414 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005415 goto err;
Willy Tarreau20879a02012-12-03 16:32:10 +01005416 }
Emeric Brun46591952012-05-18 15:47:34 +02005417
Olivier Houcharda8955d52019-04-07 22:00:38 +02005418 ctx->bio = BIO_new(ha_meth);
5419 if (!ctx->bio) {
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005420 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005421 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005422 goto retry_accept;
5423 }
Emeric Brun55476152014-11-12 17:35:37 +01005424 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005425 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005426 }
Olivier Houcharda8955d52019-04-07 22:00:38 +02005427 BIO_set_data(ctx->bio, ctx);
Olivier Houcharda8955d52019-04-07 22:00:38 +02005428 SSL_set_bio(ctx->ssl, ctx->bio, ctx->bio);
Emeric Brun46591952012-05-18 15:47:34 +02005429
Emeric Brune1f38db2012-09-03 20:36:47 +02005430 /* set connection pointer */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005431 if (!SSL_set_ex_data(ctx->ssl, ssl_app_data_index, conn)) {
5432 SSL_free(ctx->ssl);
5433 ctx->ssl = NULL;
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005434 if (may_retry--) {
Willy Tarreaubafbe012017-11-24 17:34:44 +01005435 pool_gc(NULL);
Willy Tarreaufba03cd2014-11-13 13:48:58 +01005436 goto retry_accept;
5437 }
Emeric Brun55476152014-11-12 17:35:37 +01005438 conn->err_code = CO_ER_SSL_NO_MEM;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005439 goto err;
Emeric Brun55476152014-11-12 17:35:37 +01005440 }
5441
Olivier Houchard66ab4982019-02-26 18:37:15 +01005442 SSL_set_accept_state(ctx->ssl);
Emeric Brune1f38db2012-09-03 20:36:47 +02005443
Emeric Brun46591952012-05-18 15:47:34 +02005444 /* leave init state and start handshake */
Willy Tarreau05737472012-09-04 08:03:39 +02005445 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005446#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005447 conn->flags |= CO_FL_EARLY_SSL_HS;
5448#endif
Willy Tarreau403edff2012-09-06 11:58:37 +02005449
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01005450 _HA_ATOMIC_ADD(&sslconns, 1);
5451 _HA_ATOMIC_ADD(&totalsslconns, 1);
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005452 *xprt_ctx = ctx;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005453 /* Start the handshake */
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005454 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005455 if (conn->flags & CO_FL_ERROR)
5456 goto err;
Emeric Brun46591952012-05-18 15:47:34 +02005457 return 0;
5458 }
5459 /* don't know how to handle such a target */
Willy Tarreau20879a02012-12-03 16:32:10 +01005460 conn->err_code = CO_ER_SSL_NO_TARGET;
Olivier Houchard66ab4982019-02-26 18:37:15 +01005461err:
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005462 if (ctx && ctx->wait_event.tasklet)
5463 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01005464 pool_free(ssl_sock_ctx_pool, ctx);
Emeric Brun46591952012-05-18 15:47:34 +02005465 return -1;
5466}
5467
5468
5469/* This is the callback which is used when an SSL handshake is pending. It
5470 * updates the FD status if it wants some polling before being called again.
5471 * It returns 0 if it fails in a fatal way or needs to poll to go further,
5472 * otherwise it returns non-zero and removes itself from the connection's
5473 * flags (the bit is provided in <flag> by the caller).
5474 */
Olivier Houchard000694c2019-05-23 14:45:12 +02005475static int ssl_sock_handshake(struct connection *conn, unsigned int flag)
Emeric Brun46591952012-05-18 15:47:34 +02005476{
Olivier Houchard66ab4982019-02-26 18:37:15 +01005477 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
Emeric Brun46591952012-05-18 15:47:34 +02005478 int ret;
5479
Willy Tarreau3c728722014-01-23 13:50:42 +01005480 if (!conn_ctrl_ready(conn))
Willy Tarreauf79c8172013-10-21 16:30:56 +02005481 return 0;
5482
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02005483 if (!conn->xprt_ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005484 goto out_error;
5485
Willy Tarreau5db847a2019-05-09 14:13:35 +02005486#if HA_OPENSSL_VERSION_NUMBER >= 0x10101000L
Olivier Houchardc2aae742017-09-22 18:26:28 +02005487 /*
5488 * Check if we have early data. If we do, we have to read them
5489 * before SSL_do_handshake() is called, And there's no way to
5490 * detect early data, except to try to read them
5491 */
5492 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5493 size_t read_data;
5494
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005495 ret = SSL_read_early_data(ctx->ssl, &ctx->tmp_early_data,
Olivier Houchardc2aae742017-09-22 18:26:28 +02005496 1, &read_data);
5497 if (ret == SSL_READ_EARLY_DATA_ERROR)
5498 goto check_error;
5499 if (ret == SSL_READ_EARLY_DATA_SUCCESS) {
5500 conn->flags &= ~(CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN);
5501 return 1;
5502 } else
5503 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5504 }
5505#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005506 /* If we use SSL_do_handshake to process a reneg initiated by
5507 * the remote peer, it sometimes returns SSL_ERROR_SSL.
5508 * Usually SSL_write and SSL_read are used and process implicitly
5509 * the reneg handshake.
5510 * Here we use SSL_peek as a workaround for reneg.
5511 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005512 if ((conn->flags & CO_FL_CONNECTED) && SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005513 char c;
5514
Olivier Houchard66ab4982019-02-26 18:37:15 +01005515 ret = SSL_peek(ctx->ssl, &c, 1);
Emeric Brun674b7432012-11-08 19:21:55 +01005516 if (ret <= 0) {
5517 /* handshake may have not been completed, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005518 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005519
Emeric Brun674b7432012-11-08 19:21:55 +01005520 if (ret == SSL_ERROR_WANT_WRITE) {
5521 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005522 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005523 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005524 return 0;
5525 }
5526 else if (ret == SSL_ERROR_WANT_READ) {
5527 /* handshake may have been completed but we have
5528 * no more data to read.
5529 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005530 if (!SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun674b7432012-11-08 19:21:55 +01005531 ret = 1;
5532 goto reneg_ok;
5533 }
5534 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005535 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005536 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun674b7432012-11-08 19:21:55 +01005537 return 0;
5538 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005539#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005540 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005541 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005542 return 0;
5543 }
5544#endif
Emeric Brun674b7432012-11-08 19:21:55 +01005545 else if (ret == SSL_ERROR_SYSCALL) {
5546 /* if errno is null, then connection was successfully established */
5547 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5548 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Willy Tarreau20879a02012-12-03 16:32:10 +01005549 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005550#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5551 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005552 conn->err_code = CO_ER_SSL_HANDSHAKE;
5553#else
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005554 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005555#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005556 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005557 OSSL_HANDSHAKE_STATE state = SSL_get_state((SSL *)ctx->ssl);
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005558 empty_handshake = state == TLS_ST_BEFORE;
5559#else
Lukas Tribus49799162019-07-08 14:29:15 +02005560 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5561 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005562#endif
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005563 if (empty_handshake) {
Emeric Brun29f037d2014-04-25 19:05:36 +02005564 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005565 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005566 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5567 else
5568 conn->err_code = CO_ER_SSL_EMPTY;
5569 }
5570 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005571 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005572 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5573 else
5574 conn->err_code = CO_ER_SSL_ABORT;
5575 }
5576 }
5577 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005578 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005579 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
Willy Tarreau20879a02012-12-03 16:32:10 +01005580 else
Emeric Brun29f037d2014-04-25 19:05:36 +02005581 conn->err_code = CO_ER_SSL_HANDSHAKE;
5582 }
Lukas Tribus49799162019-07-08 14:29:15 +02005583#endif /* BoringSSL or LibreSSL */
Willy Tarreau20879a02012-12-03 16:32:10 +01005584 }
Emeric Brun674b7432012-11-08 19:21:55 +01005585 goto out_error;
5586 }
5587 else {
5588 /* Fail on all other handshake errors */
5589 /* Note: OpenSSL may leave unread bytes in the socket's
5590 * buffer, causing an RST to be emitted upon close() on
5591 * TCP sockets. We first try to drain possibly pending
5592 * data to avoid this as much as possible.
5593 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005594 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005595 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005596 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005597 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun674b7432012-11-08 19:21:55 +01005598 goto out_error;
5599 }
5600 }
5601 /* read some data: consider handshake completed */
5602 goto reneg_ok;
5603 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01005604 ret = SSL_do_handshake(ctx->ssl);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005605check_error:
Emeric Brun46591952012-05-18 15:47:34 +02005606 if (ret != 1) {
5607 /* handshake did not complete, let's find why */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005608 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005609
5610 if (ret == SSL_ERROR_WANT_WRITE) {
5611 /* SSL handshake needs to write, L4 connection may not be ready */
Olivier Houchard03abf2d2019-05-28 10:12:02 +02005612 if (!(ctx->wait_event.events & SUB_RETRY_SEND))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005613 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005614 return 0;
5615 }
5616 else if (ret == SSL_ERROR_WANT_READ) {
5617 /* SSL handshake needs to read, L4 connection is ready */
Olivier Houchardea8dd942019-05-20 14:02:16 +02005618 if (!(ctx->wait_event.events & SUB_RETRY_RECV))
Olivier Houchardea8dd942019-05-20 14:02:16 +02005619 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
5620 SUB_RETRY_RECV, &ctx->wait_event);
Emeric Brun46591952012-05-18 15:47:34 +02005621 return 0;
5622 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005623#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005624 else if (ret == SSL_ERROR_WANT_ASYNC) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005625 ssl_async_process_fds(ctx);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00005626 return 0;
5627 }
5628#endif
Willy Tarreau89230192012-09-28 20:22:13 +02005629 else if (ret == SSL_ERROR_SYSCALL) {
5630 /* if errno is null, then connection was successfully established */
5631 if (!errno && conn->flags & CO_FL_WAIT_L4_CONN)
5632 conn->flags &= ~CO_FL_WAIT_L4_CONN;
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005633 if (!conn->err_code) {
Lukas Tribus49799162019-07-08 14:29:15 +02005634#if defined(OPENSSL_IS_BORINGSSL) || defined(LIBRESSL_VERSION_NUMBER)
5635 /* do not handle empty handshakes in BoringSSL or LibreSSL */
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005636 conn->err_code = CO_ER_SSL_HANDSHAKE;
5637#else
5638 int empty_handshake;
Willy Tarreau5db847a2019-05-09 14:13:35 +02005639#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL)
Lukas Tribus49799162019-07-08 14:29:15 +02005640 /* use SSL_get_state() in OpenSSL >= 1.1.0; SSL_state() is broken */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005641 OSSL_HANDSHAKE_STATE state = SSL_get_state(ctx->ssl);
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005642 empty_handshake = state == TLS_ST_BEFORE;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005643#else
Lukas Tribus49799162019-07-08 14:29:15 +02005644 /* access packet_length directly in OpenSSL <= 1.0.2; SSL_state() is broken */
5645 empty_handshake = !ctx->ssl->packet_length;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02005646#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005647 if (empty_handshake) {
5648 if (!errno) {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005649 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005650 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5651 else
5652 conn->err_code = CO_ER_SSL_EMPTY;
5653 }
5654 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005655 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005656 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5657 else
5658 conn->err_code = CO_ER_SSL_ABORT;
5659 }
Emeric Brun29f037d2014-04-25 19:05:36 +02005660 }
5661 else {
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005662 if (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT)
Emeric Brun29f037d2014-04-25 19:05:36 +02005663 conn->err_code = CO_ER_SSL_HANDSHAKE_HB;
5664 else
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01005665 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun29f037d2014-04-25 19:05:36 +02005666 }
Lukas Tribus49799162019-07-08 14:29:15 +02005667#endif /* BoringSSL or LibreSSL */
Emeric Brun29f037d2014-04-25 19:05:36 +02005668 }
Willy Tarreau89230192012-09-28 20:22:13 +02005669 goto out_error;
5670 }
Emeric Brun46591952012-05-18 15:47:34 +02005671 else {
5672 /* Fail on all other handshake errors */
Willy Tarreau566dc552012-10-19 20:52:18 +02005673 /* Note: OpenSSL may leave unread bytes in the socket's
5674 * buffer, causing an RST to be emitted upon close() on
5675 * TCP sockets. We first try to drain possibly pending
5676 * data to avoid this as much as possible.
5677 */
Willy Tarreaud85c4852015-03-13 00:40:28 +01005678 conn_sock_drain(conn);
Willy Tarreau20879a02012-12-03 16:32:10 +01005679 if (!conn->err_code)
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005680 conn->err_code = (ctx->xprt_st & SSL_SOCK_RECV_HEARTBEAT) ?
Willy Tarreauf51c6982014-04-25 20:02:39 +02005681 CO_ER_SSL_KILLED_HB : CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005682 goto out_error;
5683 }
5684 }
Willy Tarreau5db847a2019-05-09 14:13:35 +02005685#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard522eea72017-11-03 16:27:47 +01005686 else {
5687 /*
5688 * If the server refused the early data, we have to send a
5689 * 425 to the client, as we no longer have the data to sent
5690 * them again.
5691 */
5692 if ((conn->flags & CO_FL_EARLY_DATA) && (objt_server(conn->target))) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005693 if (SSL_get_early_data_status(ctx->ssl) == SSL_EARLY_DATA_REJECTED) {
Olivier Houchard522eea72017-11-03 16:27:47 +01005694 conn->err_code = CO_ER_SSL_EARLY_FAILED;
5695 goto out_error;
5696 }
5697 }
5698 }
5699#endif
5700
Emeric Brun46591952012-05-18 15:47:34 +02005701
Emeric Brun674b7432012-11-08 19:21:55 +01005702reneg_ok:
Emeric Brunb5e42a82017-06-06 12:35:14 +00005703
Willy Tarreau5db847a2019-05-09 14:13:35 +02005704#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005705 /* ASYNC engine API doesn't support moving read/write
5706 * buffers. So we disable ASYNC mode right after
5707 * the handshake to avoid buffer oveflows.
5708 */
5709 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005710 SSL_clear_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005711#endif
Emeric Brun46591952012-05-18 15:47:34 +02005712 /* Handshake succeeded */
Olivier Houchard66ab4982019-02-26 18:37:15 +01005713 if (!SSL_session_reused(ctx->ssl)) {
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005714 if (objt_server(conn->target)) {
5715 update_freq_ctr(&global.ssl_be_keys_per_sec, 1);
5716 if (global.ssl_be_keys_per_sec.curr_ctr > global.ssl_be_keys_max)
5717 global.ssl_be_keys_max = global.ssl_be_keys_per_sec.curr_ctr;
Emeric Brun46591952012-05-18 15:47:34 +02005718 }
Willy Tarreau0c9c2722014-05-28 12:28:58 +02005719 else {
5720 update_freq_ctr(&global.ssl_fe_keys_per_sec, 1);
5721 if (global.ssl_fe_keys_per_sec.curr_ctr > global.ssl_fe_keys_max)
5722 global.ssl_fe_keys_max = global.ssl_fe_keys_per_sec.curr_ctr;
5723 }
Emeric Brun46591952012-05-18 15:47:34 +02005724 }
5725
5726 /* The connection is now established at both layers, it's time to leave */
5727 conn->flags &= ~(flag | CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN);
5728 return 1;
5729
5730 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01005731 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02005732 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01005733 ERR_clear_error();
5734
Emeric Brun9fa89732012-10-04 17:09:56 +02005735 /* free resumed session if exists */
Willy Tarreau07d94e42018-09-20 10:57:52 +02005736 if (objt_server(conn->target) && __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr) {
5737 free(__objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr);
5738 __objt_server(conn->target)->ssl_ctx.reused_sess[tid].ptr = NULL;
Emeric Brun9fa89732012-10-04 17:09:56 +02005739 }
5740
Emeric Brun46591952012-05-18 15:47:34 +02005741 /* Fail on all other handshake errors */
5742 conn->flags |= CO_FL_ERROR;
Willy Tarreau20879a02012-12-03 16:32:10 +01005743 if (!conn->err_code)
5744 conn->err_code = CO_ER_SSL_HANDSHAKE;
Emeric Brun46591952012-05-18 15:47:34 +02005745 return 0;
5746}
5747
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005748static int ssl_subscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005749{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005750 struct wait_event *sw;
5751 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005752
Olivier Houchard0ff28652019-06-24 18:57:39 +02005753 if (!ctx)
5754 return -1;
5755
Olivier Houchardea8dd942019-05-20 14:02:16 +02005756 if (event_type & SUB_RETRY_RECV) {
5757 sw = param;
5758 BUG_ON(ctx->recv_wait != NULL || (sw->events & SUB_RETRY_RECV));
5759 sw->events |= SUB_RETRY_RECV;
5760 ctx->recv_wait = sw;
5761 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5762 !(ctx->wait_event.events & SUB_RETRY_RECV))
5763 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event);
5764 event_type &= ~SUB_RETRY_RECV;
5765 }
5766 if (event_type & SUB_RETRY_SEND) {
5767sw = param;
5768 BUG_ON(ctx->send_wait != NULL || (sw->events & SUB_RETRY_SEND));
5769 sw->events |= SUB_RETRY_SEND;
5770 ctx->send_wait = sw;
5771 if (!(conn->flags & CO_FL_SSL_WAIT_HS) &&
5772 !(ctx->wait_event.events & SUB_RETRY_SEND))
5773 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
5774 event_type &= ~SUB_RETRY_SEND;
5775
5776 }
5777 if (event_type != 0)
5778 return -1;
5779 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005780}
5781
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005782static int ssl_unsubscribe(struct connection *conn, void *xprt_ctx, int event_type, void *param)
Olivier Houcharddf357842019-03-21 16:30:07 +01005783{
Olivier Houchardea8dd942019-05-20 14:02:16 +02005784 struct wait_event *sw;
5785 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005786
Olivier Houchardea8dd942019-05-20 14:02:16 +02005787 if (event_type & SUB_RETRY_RECV) {
5788 sw = param;
5789 BUG_ON(ctx->recv_wait != sw);
5790 ctx->recv_wait = NULL;
5791 sw->events &= ~SUB_RETRY_RECV;
5792 /* If we subscribed, and we're not doing the handshake,
5793 * then we subscribed because the upper layer asked for it,
5794 * as the upper layer is no longer interested, we can
5795 * unsubscribe too.
5796 */
5797 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5798 (ctx->wait_event.events & SUB_RETRY_RECV))
5799 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_RECV,
5800 &ctx->wait_event);
5801 }
5802 if (event_type & SUB_RETRY_SEND) {
5803 sw = param;
5804 BUG_ON(ctx->send_wait != sw);
5805 ctx->send_wait = NULL;
5806 sw->events &= ~SUB_RETRY_SEND;
5807 if (!(ctx->conn->flags & CO_FL_SSL_WAIT_HS) &&
5808 (ctx->wait_event.events & SUB_RETRY_SEND))
5809 conn_unsubscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND,
5810 &ctx->wait_event);
5811
5812 }
5813
5814 return 0;
Olivier Houcharddf357842019-03-21 16:30:07 +01005815}
5816
Olivier Houchard2e055482019-05-27 19:50:12 +02005817/* Use the provided XPRT as an underlying XPRT, and provide the old one.
5818 * Returns 0 on success, and non-zero on failure.
5819 */
5820static 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)
5821{
5822 struct ssl_sock_ctx *ctx = xprt_ctx;
5823
5824 if (oldxprt_ops != NULL)
5825 *oldxprt_ops = ctx->xprt;
5826 if (oldxprt_ctx != NULL)
5827 *oldxprt_ctx = ctx->xprt_ctx;
5828 ctx->xprt = toadd_ops;
5829 ctx->xprt_ctx = toadd_ctx;
5830 return 0;
5831}
5832
Olivier Houchard5149b592019-05-23 17:47:36 +02005833/* Remove the specified xprt. If if it our underlying XPRT, remove it and
5834 * return 0, otherwise just call the remove_xprt method from the underlying
5835 * XPRT.
5836 */
5837static int ssl_remove_xprt(struct connection *conn, void *xprt_ctx, void *toremove_ctx, const struct xprt_ops *newops, void *newctx)
5838{
5839 struct ssl_sock_ctx *ctx = xprt_ctx;
5840
5841 if (ctx->xprt_ctx == toremove_ctx) {
5842 ctx->xprt_ctx = newctx;
5843 ctx->xprt = newops;
5844 return 0;
5845 }
5846 return (ctx->xprt->remove_xprt(conn, ctx->xprt_ctx, toremove_ctx, newops, newctx));
5847}
5848
Olivier Houchardea8dd942019-05-20 14:02:16 +02005849static struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned short state)
5850{
5851 struct ssl_sock_ctx *ctx = context;
5852
5853 /* First if we're doing an handshake, try that */
5854 if (ctx->conn->flags & CO_FL_SSL_WAIT_HS)
5855 ssl_sock_handshake(ctx->conn, CO_FL_SSL_WAIT_HS);
5856 /* If we had an error, or the handshake is done and I/O is available,
5857 * let the upper layer know.
5858 * If no mux was set up yet, and nobody subscribed, then call
5859 * xprt_done_cb() ourself if it's set, or destroy the connection,
5860 * we can't be sure conn_fd_handler() will be called again.
5861 */
5862 if ((ctx->conn->flags & CO_FL_ERROR) ||
5863 !(ctx->conn->flags & CO_FL_SSL_WAIT_HS)) {
5864 int ret = 0;
5865 int woke = 0;
5866
5867 /* On error, wake any waiter */
5868 if (ctx->recv_wait) {
5869 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005870 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005871 ctx->recv_wait = NULL;
5872 woke = 1;
5873 }
5874 if (ctx->send_wait) {
5875 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02005876 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02005877 ctx->send_wait = NULL;
5878 woke = 1;
5879 }
5880 /* If we're the first xprt for the connection, let the
5881 * upper layers know. If xprt_done_cb() is set, call it,
5882 * otherwise, we should have a mux, so call its wake
5883 * method if we didn't woke a tasklet already.
5884 */
5885 if (ctx->conn->xprt_ctx == ctx) {
5886 if (ctx->conn->xprt_done_cb)
5887 ret = ctx->conn->xprt_done_cb(ctx->conn);
5888 if (ret >= 0 && !woke && ctx->conn->mux && ctx->conn->mux->wake)
5889 ctx->conn->mux->wake(ctx->conn);
5890 return NULL;
5891 }
5892 }
5893 return NULL;
5894}
5895
Emeric Brun46591952012-05-18 15:47:34 +02005896/* Receive up to <count> bytes from connection <conn>'s socket and store them
Willy Tarreauabf08d92014-01-14 11:31:27 +01005897 * into buffer <buf>. Only one call to recv() is performed, unless the
Emeric Brun46591952012-05-18 15:47:34 +02005898 * buffer wraps, in which case a second call may be performed. The connection's
5899 * flags are updated with whatever special event is detected (error, read0,
5900 * empty). The caller is responsible for taking care of those events and
5901 * avoiding the call if inappropriate. The function does not call the
5902 * connection's polling update function, so the caller is responsible for this.
5903 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005904static 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 +02005905{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005906 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreaubfc4d772018-07-18 11:22:03 +02005907 ssize_t ret;
5908 size_t try, done = 0;
Emeric Brun46591952012-05-18 15:47:34 +02005909
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02005910 conn_refresh_polling_flags(conn);
5911
Olivier Houcharde179d0e2019-03-21 18:27:17 +01005912 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02005913 goto out_error;
5914
5915 if (conn->flags & CO_FL_HANDSHAKE)
5916 /* a handshake was requested */
5917 return 0;
5918
Emeric Brun46591952012-05-18 15:47:34 +02005919 /* read the largest possible block. For this, we perform only one call
5920 * to recv() unless the buffer wraps and we exactly fill the first hunk,
5921 * in which case we accept to do it once again. A new attempt is made on
5922 * EINTR too.
5923 */
Willy Tarreau00b0fb92014-01-17 11:09:40 +01005924 while (count > 0) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02005925 int need_out = 0;
5926
Willy Tarreau591d4452018-06-15 17:21:00 +02005927 try = b_contig_space(buf);
5928 if (!try)
5929 break;
5930
Willy Tarreauabf08d92014-01-14 11:31:27 +01005931 if (try > count)
5932 try = count;
Willy Tarreau591d4452018-06-15 17:21:00 +02005933
Olivier Houchardc2aae742017-09-22 18:26:28 +02005934 if (((conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_EARLY_DATA)) == CO_FL_EARLY_SSL_HS) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005935 ctx->tmp_early_data != -1) {
5936 *b_tail(buf) = ctx->tmp_early_data;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005937 done++;
5938 try--;
5939 count--;
Olivier Houchardacd14032018-06-28 18:17:23 +02005940 b_add(buf, 1);
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01005941 ctx->tmp_early_data = -1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02005942 continue;
5943 }
Willy Tarreauabf08d92014-01-14 11:31:27 +01005944
Willy Tarreau5db847a2019-05-09 14:13:35 +02005945#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005946 if (conn->flags & CO_FL_EARLY_SSL_HS) {
5947 size_t read_length;
5948
Olivier Houchard66ab4982019-02-26 18:37:15 +01005949 ret = SSL_read_early_data(ctx->ssl,
Willy Tarreau8f9c72d2018-06-07 18:46:28 +02005950 b_tail(buf), try, &read_length);
Olivier Houchard522eea72017-11-03 16:27:47 +01005951 if (ret == SSL_READ_EARLY_DATA_SUCCESS &&
5952 read_length > 0)
Olivier Houchardc2aae742017-09-22 18:26:28 +02005953 conn->flags |= CO_FL_EARLY_DATA;
5954 if (ret == SSL_READ_EARLY_DATA_SUCCESS ||
5955 ret == SSL_READ_EARLY_DATA_FINISH) {
5956 if (ret == SSL_READ_EARLY_DATA_FINISH) {
5957 /*
5958 * We're done reading the early data,
5959 * let's make the handshake
5960 */
5961 conn->flags &= ~CO_FL_EARLY_SSL_HS;
5962 conn->flags |= CO_FL_SSL_WAIT_HS;
5963 need_out = 1;
Olivier Houchard965e84e2019-06-15 20:59:30 +02005964 /* Now initiate the handshake */
5965 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02005966 if (read_length == 0)
5967 break;
5968 }
5969 ret = read_length;
5970 }
5971 } else
5972#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01005973 ret = SSL_read(ctx->ssl, b_tail(buf), try);
Emmanuel Hocdetf967c312019-08-05 18:04:16 +02005974
Emeric Brune1f38db2012-09-03 20:36:47 +02005975 if (conn->flags & CO_FL_ERROR) {
5976 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01005977 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02005978 }
Emeric Brun46591952012-05-18 15:47:34 +02005979 if (ret > 0) {
Olivier Houchardacd14032018-06-28 18:17:23 +02005980 b_add(buf, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005981 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02005982 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02005983 }
Emeric Brun46591952012-05-18 15:47:34 +02005984 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005985 ret = SSL_get_error(ctx->ssl, ret);
Emeric Brun46591952012-05-18 15:47:34 +02005986 if (ret == SSL_ERROR_WANT_WRITE) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01005987 /* handshake is running, and it needs to enable write */
Emeric Brun46591952012-05-18 15:47:34 +02005988 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02005989 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02005990#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00005991 /* Async mode can be re-enabled, because we're leaving data state.*/
5992 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01005993 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00005994#endif
Emeric Brun46591952012-05-18 15:47:34 +02005995 break;
5996 }
5997 else if (ret == SSL_ERROR_WANT_READ) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01005998 if (SSL_renegotiate_pending(ctx->ssl)) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02005999 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6000 SUB_RETRY_RECV,
6001 &ctx->wait_event);
Emeric Brun282a76a2012-11-08 18:02:56 +01006002 /* handshake is running, and it may need to re-enable read */
6003 conn->flags |= CO_FL_SSL_WAIT_HS;
Willy Tarreau5db847a2019-05-09 14:13:35 +02006004#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006005 /* Async mode can be re-enabled, because we're leaving data state.*/
6006 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006007 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006008#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006009 break;
6010 }
Emeric Brun46591952012-05-18 15:47:34 +02006011 break;
Olivier Houchardc2aae742017-09-22 18:26:28 +02006012 } else if (ret == SSL_ERROR_ZERO_RETURN)
6013 goto read0;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006014 /* For SSL_ERROR_SYSCALL, make sure to clear the error
6015 * stack before shutting down the connection for
6016 * reading. */
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006017 if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN))
6018 goto clear_ssl_error;
Emeric Brun46591952012-05-18 15:47:34 +02006019 /* otherwise it's a real error */
6020 goto out_error;
6021 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006022 if (need_out)
6023 break;
Emeric Brun46591952012-05-18 15:47:34 +02006024 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006025 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006026 return done;
6027
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006028 clear_ssl_error:
6029 /* Clear openssl global errors stack */
6030 ssl_sock_dump_errors(conn);
6031 ERR_clear_error();
Emeric Brun46591952012-05-18 15:47:34 +02006032 read0:
6033 conn_sock_read0(conn);
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006034 goto leave;
Christopher Faulet4ac77a92018-02-19 14:25:15 +01006035
Emeric Brun46591952012-05-18 15:47:34 +02006036 out_error:
Olivier Houchard7e2e5052018-02-13 15:17:23 +01006037 conn->flags |= CO_FL_ERROR;
Emeric Brun644cde02012-12-14 11:21:13 +01006038 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006039 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006040 ERR_clear_error();
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006041 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006042}
6043
6044
Willy Tarreau787db9a2018-06-14 18:31:46 +02006045/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
6046 * socket. <flags> may contain some CO_SFL_* flags to hint the system about
6047 * other pending data for example, but this flag is ignored at the moment.
Emeric Brun46591952012-05-18 15:47:34 +02006048 * Only one call to send() is performed, unless the buffer wraps, in which case
6049 * a second call may be performed. The connection's flags are updated with
6050 * whatever special event is detected (error, empty). The caller is responsible
6051 * for taking care of those events and avoiding the call if inappropriate. The
6052 * function does not call the connection's polling update function, so the caller
Willy Tarreau787db9a2018-06-14 18:31:46 +02006053 * is responsible for this. The buffer's output is not adjusted, it's up to the
6054 * caller to take care of this. It's up to the caller to update the buffer's
6055 * contents based on the return value.
Emeric Brun46591952012-05-18 15:47:34 +02006056 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006057static 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 +02006058{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006059 struct ssl_sock_ctx *ctx = xprt_ctx;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006060 ssize_t ret;
6061 size_t try, done;
Emeric Brun46591952012-05-18 15:47:34 +02006062
6063 done = 0;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006064 conn_refresh_polling_flags(conn);
Emeric Brun46591952012-05-18 15:47:34 +02006065
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006066 if (!ctx)
Emeric Brun46591952012-05-18 15:47:34 +02006067 goto out_error;
6068
Olivier Houchard010941f2019-05-03 20:56:19 +02006069 if (conn->flags & (CO_FL_HANDSHAKE | CO_FL_EARLY_SSL_HS))
Emeric Brun46591952012-05-18 15:47:34 +02006070 /* a handshake was requested */
6071 return 0;
6072
6073 /* send the largest possible block. For this we perform only one call
6074 * to send() unless the buffer wraps and we exactly fill the first hunk,
6075 * in which case we accept to do it once again.
6076 */
Willy Tarreau787db9a2018-06-14 18:31:46 +02006077 while (count) {
Willy Tarreau5db847a2019-05-09 14:13:35 +02006078#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchardc2aae742017-09-22 18:26:28 +02006079 size_t written_data;
6080#endif
6081
Willy Tarreau787db9a2018-06-14 18:31:46 +02006082 try = b_contig_data(buf, done);
6083 if (try > count)
6084 try = count;
Willy Tarreaubfd59462013-02-21 07:46:09 +01006085
Willy Tarreau7bed9452014-02-02 02:00:24 +01006086 if (!(flags & CO_SFL_STREAMER) &&
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006087 !(ctx->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
Willy Tarreauef934602016-12-22 23:12:01 +01006088 global_ssl.max_record && try > global_ssl.max_record) {
6089 try = global_ssl.max_record;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006090 }
6091 else {
6092 /* we need to keep the information about the fact that
6093 * we're not limiting the upcoming send(), because if it
6094 * fails, we'll have to retry with at least as many data.
6095 */
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006096 ctx->xprt_st |= SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau518cedd2014-02-17 15:43:01 +01006097 }
Willy Tarreaubfd59462013-02-21 07:46:09 +01006098
Willy Tarreau5db847a2019-05-09 14:13:35 +02006099#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Olivier Houchard010941f2019-05-03 20:56:19 +02006100 if (!SSL_is_init_finished(ctx->ssl) && conn_is_back(conn)) {
Olivier Houchardc2aae742017-09-22 18:26:28 +02006101 unsigned int max_early;
6102
Olivier Houchard522eea72017-11-03 16:27:47 +01006103 if (objt_listener(conn->target))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006104 max_early = SSL_get_max_early_data(ctx->ssl);
Olivier Houchard522eea72017-11-03 16:27:47 +01006105 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006106 if (SSL_get0_session(ctx->ssl))
6107 max_early = SSL_SESSION_get_max_early_data(SSL_get0_session(ctx->ssl));
Olivier Houchard522eea72017-11-03 16:27:47 +01006108 else
6109 max_early = 0;
6110 }
6111
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006112 if (try + ctx->sent_early_data > max_early) {
6113 try -= (try + ctx->sent_early_data) - max_early;
Olivier Houchard522eea72017-11-03 16:27:47 +01006114 if (try <= 0) {
Olivier Houchard010941f2019-05-03 20:56:19 +02006115 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006116 tasklet_wakeup(ctx->wait_event.tasklet);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006117 break;
Olivier Houchard522eea72017-11-03 16:27:47 +01006118 }
Olivier Houchardc2aae742017-09-22 18:26:28 +02006119 }
Olivier Houchard66ab4982019-02-26 18:37:15 +01006120 ret = SSL_write_early_data(ctx->ssl, b_peek(buf, done), try, &written_data);
Olivier Houchardc2aae742017-09-22 18:26:28 +02006121 if (ret == 1) {
6122 ret = written_data;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006123 ctx->sent_early_data += ret;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006124 if (objt_server(conn->target)) {
Olivier Houchard522eea72017-11-03 16:27:47 +01006125 conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN | CO_FL_EARLY_DATA;
Olivier Houchard965e84e2019-06-15 20:59:30 +02006126 /* Initiate the handshake, now */
6127 tasklet_wakeup(ctx->wait_event.tasklet);
6128 }
Olivier Houchard522eea72017-11-03 16:27:47 +01006129
Olivier Houchardc2aae742017-09-22 18:26:28 +02006130 }
6131
6132 } else
6133#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006134 ret = SSL_write(ctx->ssl, b_peek(buf, done), try);
Willy Tarreau518cedd2014-02-17 15:43:01 +01006135
Emeric Brune1f38db2012-09-03 20:36:47 +02006136 if (conn->flags & CO_FL_ERROR) {
6137 /* CO_FL_ERROR may be set by ssl_sock_infocbk */
Emeric Brun644cde02012-12-14 11:21:13 +01006138 goto out_error;
Emeric Brune1f38db2012-09-03 20:36:47 +02006139 }
Emeric Brun46591952012-05-18 15:47:34 +02006140 if (ret > 0) {
Olivier Houchardf24502b2019-01-17 19:09:11 +01006141 /* A send succeeded, so we can consier ourself connected */
6142 conn->flags |= CO_FL_CONNECTED;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006143 ctx->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
Willy Tarreau787db9a2018-06-14 18:31:46 +02006144 count -= ret;
Emeric Brun46591952012-05-18 15:47:34 +02006145 done += ret;
Emeric Brun46591952012-05-18 15:47:34 +02006146 }
6147 else {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006148 ret = SSL_get_error(ctx->ssl, ret);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006149
Emeric Brun46591952012-05-18 15:47:34 +02006150 if (ret == SSL_ERROR_WANT_WRITE) {
Olivier Houchard66ab4982019-02-26 18:37:15 +01006151 if (SSL_renegotiate_pending(ctx->ssl)) {
Emeric Brun282a76a2012-11-08 18:02:56 +01006152 /* handshake is running, and it may need to re-enable write */
6153 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006154 ctx->xprt->subscribe(conn, ctx->xprt_ctx, SUB_RETRY_SEND, &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006155#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006156 /* Async mode can be re-enabled, because we're leaving data state.*/
6157 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006158 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006159#endif
Emeric Brun282a76a2012-11-08 18:02:56 +01006160 break;
6161 }
Olivier Houchardea8dd942019-05-20 14:02:16 +02006162
Emeric Brun46591952012-05-18 15:47:34 +02006163 break;
6164 }
6165 else if (ret == SSL_ERROR_WANT_READ) {
Emeric Brun8af8dd12012-11-08 17:56:20 +01006166 /* handshake is running, and it needs to enable read */
Emeric Brun46591952012-05-18 15:47:34 +02006167 conn->flags |= CO_FL_SSL_WAIT_HS;
Olivier Houchardea8dd942019-05-20 14:02:16 +02006168 ctx->xprt->subscribe(conn, ctx->xprt_ctx,
6169 SUB_RETRY_RECV,
6170 &ctx->wait_event);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006171#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brunb5e42a82017-06-06 12:35:14 +00006172 /* Async mode can be re-enabled, because we're leaving data state.*/
6173 if (global_ssl.async)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006174 SSL_set_mode(ctx->ssl, SSL_MODE_ASYNC);
Emeric Brunb5e42a82017-06-06 12:35:14 +00006175#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006176 break;
6177 }
Emeric Brun46591952012-05-18 15:47:34 +02006178 goto out_error;
6179 }
6180 }
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006181 leave:
Emeric Brun46591952012-05-18 15:47:34 +02006182 return done;
6183
6184 out_error:
Emeric Brun644cde02012-12-14 11:21:13 +01006185 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006186 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006187 ERR_clear_error();
6188
Emeric Brun46591952012-05-18 15:47:34 +02006189 conn->flags |= CO_FL_ERROR;
Willy Tarreau31d4dbe2017-10-25 09:32:15 +02006190 goto leave;
Emeric Brun46591952012-05-18 15:47:34 +02006191}
6192
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006193static void ssl_sock_close(struct connection *conn, void *xprt_ctx) {
Emeric Brun46591952012-05-18 15:47:34 +02006194
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006195 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006196
Olivier Houchardea8dd942019-05-20 14:02:16 +02006197
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006198 if (ctx) {
Olivier Houchardea8dd942019-05-20 14:02:16 +02006199 if (ctx->wait_event.events != 0)
6200 ctx->xprt->unsubscribe(ctx->conn, ctx->xprt_ctx,
6201 ctx->wait_event.events,
6202 &ctx->wait_event);
6203 if (ctx->send_wait) {
6204 ctx->send_wait->events &= ~SUB_RETRY_SEND;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006205 tasklet_wakeup(ctx->send_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006206 }
6207 if (ctx->recv_wait) {
6208 ctx->recv_wait->events &= ~SUB_RETRY_RECV;
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006209 tasklet_wakeup(ctx->recv_wait->tasklet);
Olivier Houchardea8dd942019-05-20 14:02:16 +02006210 }
Olivier Houchard692c1d02019-05-23 18:41:47 +02006211 if (ctx->xprt->close)
6212 ctx->xprt->close(conn, ctx->xprt_ctx);
Willy Tarreau5db847a2019-05-09 14:13:35 +02006213#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Emeric Brun3854e012017-05-17 20:42:48 +02006214 if (global_ssl.async) {
6215 OSSL_ASYNC_FD all_fd[32], afd;
6216 size_t num_all_fds = 0;
6217 int i;
6218
Olivier Houchard66ab4982019-02-26 18:37:15 +01006219 SSL_get_all_async_fds(ctx->ssl, NULL, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006220 if (num_all_fds > 32) {
6221 send_log(NULL, LOG_EMERG, "haproxy: openssl returns too many async fds. It seems a bug. Process may crash\n");
6222 return;
6223 }
6224
Olivier Houchard66ab4982019-02-26 18:37:15 +01006225 SSL_get_all_async_fds(ctx->ssl, all_fd, &num_all_fds);
Emeric Brun3854e012017-05-17 20:42:48 +02006226
6227 /* If an async job is pending, we must try to
6228 to catch the end using polling before calling
6229 SSL_free */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006230 if (num_all_fds && SSL_waiting_for_async(ctx->ssl)) {
Emeric Brun3854e012017-05-17 20:42:48 +02006231 for (i=0 ; i < num_all_fds ; i++) {
6232 /* switch on an handler designed to
6233 * handle the SSL_free
6234 */
6235 afd = all_fd[i];
6236 fdtab[afd].iocb = ssl_async_fd_free;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006237 fdtab[afd].owner = ctx->ssl;
Emeric Brun3854e012017-05-17 20:42:48 +02006238 fd_want_recv(afd);
Emeric Brunce9e01c2017-05-31 10:02:53 +00006239 /* To ensure that the fd cache won't be used
6240 * and we'll catch a real RD event.
6241 */
6242 fd_cant_recv(afd);
Emeric Brun3854e012017-05-17 20:42:48 +02006243 }
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006244 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006245 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006246 _HA_ATOMIC_ADD(&jobs, 1);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006247 return;
6248 }
Emeric Brun3854e012017-05-17 20:42:48 +02006249 /* Else we can remove the fds from the fdtab
6250 * and call SSL_free.
6251 * note: we do a fd_remove and not a delete
6252 * because the fd is owned by the engine.
6253 * the engine is responsible to close
6254 */
6255 for (i=0 ; i < num_all_fds ; i++)
6256 fd_remove(all_fd[i]);
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00006257 }
6258#endif
Olivier Houchard66ab4982019-02-26 18:37:15 +01006259 SSL_free(ctx->ssl);
Willy Tarreau3c39a7d2019-06-14 14:42:29 +02006260 tasklet_free(ctx->wait_event.tasklet);
Olivier Houchard66ab4982019-02-26 18:37:15 +01006261 pool_free(ssl_sock_ctx_pool, ctx);
Olivier Houchard2be5a4c2019-03-08 18:54:43 +01006262 _HA_ATOMIC_SUB(&sslconns, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006263 }
Emeric Brun46591952012-05-18 15:47:34 +02006264}
6265
6266/* This function tries to perform a clean shutdown on an SSL connection, and in
6267 * any case, flags the connection as reusable if no handshake was in progress.
6268 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006269static void ssl_sock_shutw(struct connection *conn, void *xprt_ctx, int clean)
Emeric Brun46591952012-05-18 15:47:34 +02006270{
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006271 struct ssl_sock_ctx *ctx = xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006272
Emeric Brun46591952012-05-18 15:47:34 +02006273 if (conn->flags & CO_FL_HANDSHAKE)
6274 return;
Emmanuel Hocdet405ff312017-01-08 14:07:39 +01006275 if (!clean)
6276 /* don't sent notify on SSL_shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006277 SSL_set_quiet_shutdown(ctx->ssl, 1);
Emeric Brun46591952012-05-18 15:47:34 +02006278 /* no handshake was in progress, try a clean ssl shutdown */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006279 if (SSL_shutdown(ctx->ssl) <= 0) {
Emeric Brun644cde02012-12-14 11:21:13 +01006280 /* Clear openssl global errors stack */
Thierry FOURNIER / OZON.IO8b068c22016-10-10 11:59:50 +02006281 ssl_sock_dump_errors(conn);
Emeric Brun644cde02012-12-14 11:21:13 +01006282 ERR_clear_error();
6283 }
Emeric Brun46591952012-05-18 15:47:34 +02006284}
6285
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006286/* used for ppv2 pkey alog (can be used for logging) */
Willy Tarreau83061a82018-07-13 11:56:34 +02006287int ssl_sock_get_pkey_algo(struct connection *conn, struct buffer *out)
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006288{
Christopher Faulet82004142019-09-10 10:12:03 +02006289 struct ssl_sock_ctx *ctx;
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006290 struct pkey_info *pkinfo;
6291 int bits = 0;
6292 int sig = TLSEXT_signature_anonymous;
6293 int len = -1;
6294
6295 if (!ssl_sock_is_ssl(conn))
6296 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006297 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006298 pkinfo = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ctx->ssl), ssl_pkey_info_index);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006299 if (pkinfo) {
6300 sig = pkinfo->sig;
6301 bits = pkinfo->bits;
6302 } else {
6303 /* multicert and generated cert have no pkey info */
6304 X509 *crt;
6305 EVP_PKEY *pkey;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006306 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet96b78342017-10-31 15:46:07 +01006307 if (!crt)
6308 return 0;
6309 pkey = X509_get_pubkey(crt);
6310 if (pkey) {
6311 bits = EVP_PKEY_bits(pkey);
6312 switch(EVP_PKEY_base_id(pkey)) {
6313 case EVP_PKEY_RSA:
6314 sig = TLSEXT_signature_rsa;
6315 break;
6316 case EVP_PKEY_EC:
6317 sig = TLSEXT_signature_ecdsa;
6318 break;
6319 case EVP_PKEY_DSA:
6320 sig = TLSEXT_signature_dsa;
6321 break;
6322 }
6323 EVP_PKEY_free(pkey);
6324 }
6325 }
6326
6327 switch(sig) {
6328 case TLSEXT_signature_rsa:
6329 len = chunk_printf(out, "RSA%d", bits);
6330 break;
6331 case TLSEXT_signature_ecdsa:
6332 len = chunk_printf(out, "EC%d", bits);
6333 break;
6334 case TLSEXT_signature_dsa:
6335 len = chunk_printf(out, "DSA%d", bits);
6336 break;
6337 default:
6338 return 0;
6339 }
6340 if (len < 0)
6341 return 0;
6342 return 1;
6343}
6344
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006345/* used for ppv2 cert signature (can be used for logging) */
6346const char *ssl_sock_get_cert_sig(struct connection *conn)
6347{
Christopher Faulet82004142019-09-10 10:12:03 +02006348 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006349
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006350 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
6351 X509 *crt;
6352
6353 if (!ssl_sock_is_ssl(conn))
6354 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006355 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006356 crt = SSL_get_certificate(ctx->ssl);
Emmanuel Hocdet283e0042017-11-02 14:05:23 +01006357 if (!crt)
6358 return NULL;
6359 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
6360 return OBJ_nid2sn(OBJ_obj2nid(algorithm));
6361}
6362
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006363/* used for ppv2 authority */
6364const char *ssl_sock_get_sni(struct connection *conn)
6365{
6366#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006367 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006368
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006369 if (!ssl_sock_is_ssl(conn))
6370 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006371 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006372 return SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006373#else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006374 return NULL;
Emmanuel Hocdet253c3b72018-02-01 18:29:59 +01006375#endif
6376}
6377
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006378/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006379const char *ssl_sock_get_cipher_name(struct connection *conn)
6380{
Christopher Faulet82004142019-09-10 10:12:03 +02006381 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006382
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006383 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006384 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006385 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006386 return SSL_get_cipher_name(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006387}
6388
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006389/* used for logging/ppv2, may be changed for a sample fetch later */
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006390const char *ssl_sock_get_proto_version(struct connection *conn)
6391{
Christopher Faulet82004142019-09-10 10:12:03 +02006392 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006393
Emmanuel Hocdet01da5712017-10-13 16:59:49 +02006394 if (!ssl_sock_is_ssl(conn))
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006395 return NULL;
Christopher Faulet82004142019-09-10 10:12:03 +02006396 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006397 return SSL_get_version(ctx->ssl);
Willy Tarreauffc3fcd2012-10-12 20:17:54 +02006398}
6399
Willy Tarreau8d598402012-10-22 17:58:39 +02006400/* Extract a serial from a cert, and copy it to a chunk.
6401 * Returns 1 if serial is found and copied, 0 if no serial found and
6402 * -1 if output is not large enough.
6403 */
6404static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006405ssl_sock_get_serial(X509 *crt, struct buffer *out)
Willy Tarreau8d598402012-10-22 17:58:39 +02006406{
6407 ASN1_INTEGER *serial;
6408
6409 serial = X509_get_serialNumber(crt);
6410 if (!serial)
6411 return 0;
6412
6413 if (out->size < serial->length)
6414 return -1;
6415
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006416 memcpy(out->area, serial->data, serial->length);
6417 out->data = serial->length;
Willy Tarreau8d598402012-10-22 17:58:39 +02006418 return 1;
6419}
6420
Emeric Brun43e79582014-10-29 19:03:26 +01006421/* Extract a cert to der, and copy it to a chunk.
Joseph Herlant017b3da2018-11-15 09:07:59 -08006422 * Returns 1 if the cert is found and copied, 0 on der conversion failure
6423 * and -1 if the output is not large enough.
Emeric Brun43e79582014-10-29 19:03:26 +01006424 */
6425static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006426ssl_sock_crt2der(X509 *crt, struct buffer *out)
Emeric Brun43e79582014-10-29 19:03:26 +01006427{
6428 int len;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006429 unsigned char *p = (unsigned char *) out->area;;
Emeric Brun43e79582014-10-29 19:03:26 +01006430
6431 len =i2d_X509(crt, NULL);
6432 if (len <= 0)
6433 return 1;
6434
6435 if (out->size < len)
6436 return -1;
6437
6438 i2d_X509(crt,&p);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006439 out->data = len;
Emeric Brun43e79582014-10-29 19:03:26 +01006440 return 1;
6441}
6442
Emeric Brunce5ad802012-10-22 14:11:22 +02006443
Willy Tarreau83061a82018-07-13 11:56:34 +02006444/* Copy Date in ASN1_UTCTIME format in struct buffer out.
Emeric Brunce5ad802012-10-22 14:11:22 +02006445 * Returns 1 if serial is found and copied, 0 if no valid time found
6446 * and -1 if output is not large enough.
6447 */
6448static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006449ssl_sock_get_time(ASN1_TIME *tm, struct buffer *out)
Emeric Brunce5ad802012-10-22 14:11:22 +02006450{
6451 if (tm->type == V_ASN1_GENERALIZEDTIME) {
6452 ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
6453
6454 if (gentm->length < 12)
6455 return 0;
6456 if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
6457 return 0;
6458 if (out->size < gentm->length-2)
6459 return -1;
6460
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006461 memcpy(out->area, gentm->data+2, gentm->length-2);
6462 out->data = gentm->length-2;
Emeric Brunce5ad802012-10-22 14:11:22 +02006463 return 1;
6464 }
6465 else if (tm->type == V_ASN1_UTCTIME) {
6466 ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
6467
6468 if (utctm->length < 10)
6469 return 0;
6470 if (utctm->data[0] >= 0x35)
6471 return 0;
6472 if (out->size < utctm->length)
6473 return -1;
6474
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006475 memcpy(out->area, utctm->data, utctm->length);
6476 out->data = utctm->length;
Emeric Brunce5ad802012-10-22 14:11:22 +02006477 return 1;
6478 }
6479
6480 return 0;
6481}
6482
Emeric Brun87855892012-10-17 17:39:35 +02006483/* Extract an entry from a X509_NAME and copy its value to an output chunk.
6484 * Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
6485 */
6486static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006487ssl_sock_get_dn_entry(X509_NAME *a, const struct buffer *entry, int pos,
6488 struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006489{
6490 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006491 ASN1_OBJECT *obj;
6492 ASN1_STRING *data;
6493 const unsigned char *data_ptr;
6494 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006495 int i, j, n;
6496 int cur = 0;
6497 const char *s;
6498 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006499 int name_count;
6500
6501 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006502
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006503 out->data = 0;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006504 for (i = 0; i < name_count; i++) {
Emeric Brun87855892012-10-17 17:39:35 +02006505 if (pos < 0)
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006506 j = (name_count-1) - i;
Emeric Brun87855892012-10-17 17:39:35 +02006507 else
6508 j = i;
6509
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006510 ne = X509_NAME_get_entry(a, j);
6511 obj = X509_NAME_ENTRY_get_object(ne);
6512 data = X509_NAME_ENTRY_get_data(ne);
6513 data_ptr = ASN1_STRING_get0_data(data);
6514 data_len = ASN1_STRING_length(data);
6515 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006516 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006517 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006518 s = tmp;
6519 }
6520
6521 if (chunk_strcasecmp(entry, s) != 0)
6522 continue;
6523
6524 if (pos < 0)
6525 cur--;
6526 else
6527 cur++;
6528
6529 if (cur != pos)
6530 continue;
6531
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006532 if (data_len > out->size)
Emeric Brun87855892012-10-17 17:39:35 +02006533 return -1;
6534
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006535 memcpy(out->area, data_ptr, data_len);
6536 out->data = data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006537 return 1;
6538 }
6539
6540 return 0;
6541
6542}
6543
6544/* Extract and format full DN from a X509_NAME and copy result into a chunk
6545 * Returns 1 if dn entries exits, 0 if no dn entry found or -1 if output is not large enough.
6546 */
6547static int
Willy Tarreau83061a82018-07-13 11:56:34 +02006548ssl_sock_get_dn_oneline(X509_NAME *a, struct buffer *out)
Emeric Brun87855892012-10-17 17:39:35 +02006549{
6550 X509_NAME_ENTRY *ne;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006551 ASN1_OBJECT *obj;
6552 ASN1_STRING *data;
6553 const unsigned char *data_ptr;
6554 int data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006555 int i, n, ln;
6556 int l = 0;
6557 const char *s;
6558 char *p;
6559 char tmp[128];
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006560 int name_count;
6561
6562
6563 name_count = X509_NAME_entry_count(a);
Emeric Brun87855892012-10-17 17:39:35 +02006564
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006565 out->data = 0;
6566 p = out->area;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006567 for (i = 0; i < name_count; i++) {
6568 ne = X509_NAME_get_entry(a, i);
6569 obj = X509_NAME_ENTRY_get_object(ne);
6570 data = X509_NAME_ENTRY_get_data(ne);
6571 data_ptr = ASN1_STRING_get0_data(data);
6572 data_len = ASN1_STRING_length(data);
6573 n = OBJ_obj2nid(obj);
Emeric Brun87855892012-10-17 17:39:35 +02006574 if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006575 i2t_ASN1_OBJECT(tmp, sizeof(tmp), obj);
Emeric Brun87855892012-10-17 17:39:35 +02006576 s = tmp;
6577 }
6578 ln = strlen(s);
6579
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006580 l += 1 + ln + 1 + data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006581 if (l > out->size)
6582 return -1;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006583 out->data = l;
Emeric Brun87855892012-10-17 17:39:35 +02006584
6585 *(p++)='/';
6586 memcpy(p, s, ln);
6587 p += ln;
6588 *(p++)='=';
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02006589 memcpy(p, data_ptr, data_len);
6590 p += data_len;
Emeric Brun87855892012-10-17 17:39:35 +02006591 }
6592
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006593 if (!out->data)
Emeric Brun87855892012-10-17 17:39:35 +02006594 return 0;
6595
6596 return 1;
6597}
6598
Olivier Houchardab28a322018-12-21 19:45:40 +01006599void ssl_sock_set_alpn(struct connection *conn, const unsigned char *alpn, int len)
6600{
6601#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Christopher Faulet82004142019-09-10 10:12:03 +02006602 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006603
Olivier Houcharde488ea82019-06-28 14:10:33 +02006604 if (!ssl_sock_is_ssl(conn))
6605 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006606 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006607 SSL_set_alpn_protos(ctx->ssl, alpn, len);
Olivier Houchardab28a322018-12-21 19:45:40 +01006608#endif
6609}
6610
Willy Tarreau119a4082016-12-22 21:58:38 +01006611/* Sets advertised SNI for outgoing connections. Please set <hostname> to NULL
6612 * to disable SNI.
6613 */
Willy Tarreau63076412015-07-10 11:33:32 +02006614void ssl_sock_set_servername(struct connection *conn, const char *hostname)
6615{
6616#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Christopher Faulet82004142019-09-10 10:12:03 +02006617 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006618
Willy Tarreau119a4082016-12-22 21:58:38 +01006619 char *prev_name;
6620
Willy Tarreau63076412015-07-10 11:33:32 +02006621 if (!ssl_sock_is_ssl(conn))
6622 return;
Christopher Faulet82004142019-09-10 10:12:03 +02006623 ctx = conn->xprt_ctx;
Willy Tarreau63076412015-07-10 11:33:32 +02006624
Willy Tarreau119a4082016-12-22 21:58:38 +01006625 /* if the SNI changes, we must destroy the reusable context so that a
6626 * new connection will present a new SNI. As an optimization we could
6627 * later imagine having a small cache of ssl_ctx to hold a few SNI per
6628 * server.
6629 */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006630 prev_name = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau119a4082016-12-22 21:58:38 +01006631 if ((!prev_name && hostname) ||
6632 (prev_name && (!hostname || strcmp(hostname, prev_name) != 0)))
Olivier Houchard66ab4982019-02-26 18:37:15 +01006633 SSL_set_session(ctx->ssl, NULL);
Willy Tarreau119a4082016-12-22 21:58:38 +01006634
Olivier Houchard66ab4982019-02-26 18:37:15 +01006635 SSL_set_tlsext_host_name(ctx->ssl, hostname);
Willy Tarreau63076412015-07-10 11:33:32 +02006636#endif
6637}
6638
Emeric Brun0abf8362014-06-24 18:26:41 +02006639/* Extract peer certificate's common name into the chunk dest
6640 * Returns
6641 * the len of the extracted common name
6642 * or 0 if no CN found in DN
6643 * or -1 on error case (i.e. no peer certificate)
6644 */
Willy Tarreau83061a82018-07-13 11:56:34 +02006645int ssl_sock_get_remote_common_name(struct connection *conn,
6646 struct buffer *dest)
David Safb76832014-05-08 23:42:08 -04006647{
Christopher Faulet82004142019-09-10 10:12:03 +02006648 struct ssl_sock_ctx *ctx;
David Safb76832014-05-08 23:42:08 -04006649 X509 *crt = NULL;
6650 X509_NAME *name;
David Safb76832014-05-08 23:42:08 -04006651 const char find_cn[] = "CN";
Willy Tarreau83061a82018-07-13 11:56:34 +02006652 const struct buffer find_cn_chunk = {
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006653 .area = (char *)&find_cn,
6654 .data = sizeof(find_cn)-1
David Safb76832014-05-08 23:42:08 -04006655 };
Emeric Brun0abf8362014-06-24 18:26:41 +02006656 int result = -1;
David Safb76832014-05-08 23:42:08 -04006657
6658 if (!ssl_sock_is_ssl(conn))
Emeric Brun0abf8362014-06-24 18:26:41 +02006659 goto out;
Christopher Faulet82004142019-09-10 10:12:03 +02006660 ctx = conn->xprt_ctx;
David Safb76832014-05-08 23:42:08 -04006661
6662 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006663 crt = SSL_get_peer_certificate(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006664 if (!crt)
6665 goto out;
6666
6667 name = X509_get_subject_name(crt);
6668 if (!name)
6669 goto out;
David Safb76832014-05-08 23:42:08 -04006670
Emeric Brun0abf8362014-06-24 18:26:41 +02006671 result = ssl_sock_get_dn_entry(name, &find_cn_chunk, 1, dest);
6672out:
David Safb76832014-05-08 23:42:08 -04006673 if (crt)
6674 X509_free(crt);
6675
6676 return result;
6677}
6678
Dave McCowan328fb582014-07-30 10:39:13 -04006679/* returns 1 if client passed a certificate for this session, 0 if not */
6680int ssl_sock_get_cert_used_sess(struct connection *conn)
6681{
Christopher Faulet82004142019-09-10 10:12:03 +02006682 struct ssl_sock_ctx *ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006683 X509 *crt = NULL;
6684
6685 if (!ssl_sock_is_ssl(conn))
6686 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006687 ctx = conn->xprt_ctx;
Dave McCowan328fb582014-07-30 10:39:13 -04006688
6689 /* SSL_get_peer_certificate, it increase X509 * ref count */
Olivier Houchard66ab4982019-02-26 18:37:15 +01006690 crt = SSL_get_peer_certificate(ctx->ssl);
Dave McCowan328fb582014-07-30 10:39:13 -04006691 if (!crt)
6692 return 0;
6693
6694 X509_free(crt);
6695 return 1;
6696}
6697
6698/* returns 1 if client passed a certificate for this connection, 0 if not */
6699int ssl_sock_get_cert_used_conn(struct connection *conn)
David Safb76832014-05-08 23:42:08 -04006700{
Christopher Faulet82004142019-09-10 10:12:03 +02006701 struct ssl_sock_ctx *ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006702
David Safb76832014-05-08 23:42:08 -04006703 if (!ssl_sock_is_ssl(conn))
6704 return 0;
Christopher Faulet82004142019-09-10 10:12:03 +02006705 ctx = conn->xprt_ctx;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006706 return SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
David Safb76832014-05-08 23:42:08 -04006707}
6708
6709/* returns result from SSL verify */
6710unsigned int ssl_sock_get_verify_result(struct connection *conn)
6711{
Christopher Faulet82004142019-09-10 10:12:03 +02006712 struct ssl_sock_ctx *ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006713
David Safb76832014-05-08 23:42:08 -04006714 if (!ssl_sock_is_ssl(conn))
6715 return (unsigned int)X509_V_ERR_APPLICATION_VERIFICATION;
Christopher Faulet82004142019-09-10 10:12:03 +02006716 ctx = conn->xprt_ctx;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006717 return (unsigned int)SSL_get_verify_result(ctx->ssl);
David Safb76832014-05-08 23:42:08 -04006718}
6719
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006720/* Returns the application layer protocol name in <str> and <len> when known.
6721 * Zero is returned if the protocol name was not found, otherwise non-zero is
6722 * returned. The string is allocated in the SSL context and doesn't have to be
6723 * freed by the caller. NPN is also checked if available since older versions
6724 * of openssl (1.0.1) which are more common in field only support this one.
6725 */
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006726static int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx, const char **str, int *len)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006727{
Olivier Houchard66ab4982019-02-26 18:37:15 +01006728#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation) || \
6729 defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006730 struct ssl_sock_ctx *ctx = xprt_ctx;
6731 if (!ctx)
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006732 return 0;
6733
6734 *str = NULL;
6735
6736#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Olivier Houchard66ab4982019-02-26 18:37:15 +01006737 SSL_get0_alpn_selected(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006738 if (*str)
6739 return 1;
6740#endif
Bernard Spil13c53f82018-02-15 13:34:58 +01006741#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006742 SSL_get0_next_proto_negotiated(ctx->ssl, (const unsigned char **)str, (unsigned *)len);
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006743 if (*str)
6744 return 1;
6745#endif
Olivier Houcharde179d0e2019-03-21 18:27:17 +01006746#endif
Willy Tarreau8743f7e2016-12-04 18:44:29 +01006747 return 0;
6748}
6749
Willy Tarreau7875d092012-09-10 08:20:03 +02006750/***** Below are some sample fetching functions for ACL/patterns *****/
6751
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006752static int
6753smp_fetch_ssl_fc_has_early(const struct arg *args, struct sample *smp, const char *kw, void *private)
6754{
6755 struct connection *conn;
6756
6757 conn = objt_conn(smp->sess->origin);
6758 if (!conn || conn->xprt != &ssl_sock)
6759 return 0;
6760
6761 smp->flags = 0;
6762 smp->data.type = SMP_T_BOOL;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006763#ifdef OPENSSL_IS_BORINGSSL
6764 {
6765 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
6766 smp->data.u.sint = (SSL_in_early_data(ctx->ssl) &&
6767 SSL_early_data_accepted(ctx->ssl));
6768 }
6769#else
Olivier Houchard25ae45a2017-11-29 19:51:19 +01006770 smp->data.u.sint = ((conn->flags & CO_FL_EARLY_DATA) &&
6771 (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_HANDSHAKE))) ? 1 : 0;
Emmanuel Hocdetc9858012019-08-07 14:44:49 +02006772#endif
Olivier Houchardccaa7de2017-10-02 11:51:03 +02006773 return 1;
6774}
6775
Emeric Brune64aef12012-09-21 13:15:06 +02006776/* boolean, returns true if client cert was present */
6777static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006778smp_fetch_ssl_fc_has_crt(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brune64aef12012-09-21 13:15:06 +02006779{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006780 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006781 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006782
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006783 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006784 if (!conn || conn->xprt != &ssl_sock)
Emeric Brune64aef12012-09-21 13:15:06 +02006785 return 0;
6786
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006787 ctx = conn->xprt_ctx;
6788
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006789 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brune64aef12012-09-21 13:15:06 +02006790 smp->flags |= SMP_F_MAY_CHANGE;
6791 return 0;
6792 }
6793
6794 smp->flags = 0;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006795 smp->data.type = SMP_T_BOOL;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01006796 smp->data.u.sint = SSL_SOCK_ST_FL_VERIFY_DONE & ctx->xprt_st ? 1 : 0;
Emeric Brune64aef12012-09-21 13:15:06 +02006797
6798 return 1;
6799}
6800
Emeric Brun43e79582014-10-29 19:03:26 +01006801/* binary, returns a certificate in a binary chunk (der/raw).
6802 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6803 * should be use.
6804 */
6805static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006806smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun43e79582014-10-29 19:03:26 +01006807{
6808 int cert_peer = (kw[4] == 'c') ? 1 : 0;
6809 X509 *crt = NULL;
6810 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006811 struct buffer *smp_trash;
Emeric Brun43e79582014-10-29 19:03:26 +01006812 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006813 struct ssl_sock_ctx *ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006814
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006815 conn = objt_conn(smp->sess->origin);
Emeric Brun43e79582014-10-29 19:03:26 +01006816 if (!conn || conn->xprt != &ssl_sock)
6817 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006818 ctx = conn->xprt_ctx;
Emeric Brun43e79582014-10-29 19:03:26 +01006819
6820 if (!(conn->flags & CO_FL_CONNECTED)) {
6821 smp->flags |= SMP_F_MAY_CHANGE;
6822 return 0;
6823 }
6824
6825 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006826 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006827 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006828 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun43e79582014-10-29 19:03:26 +01006829
6830 if (!crt)
6831 goto out;
6832
6833 smp_trash = get_trash_chunk();
6834 if (ssl_sock_crt2der(crt, smp_trash) <= 0)
6835 goto out;
6836
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006837 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006838 smp->data.type = SMP_T_BIN;
Emeric Brun43e79582014-10-29 19:03:26 +01006839 ret = 1;
6840out:
6841 /* SSL_get_peer_certificate, it increase X509 * ref count */
6842 if (cert_peer && crt)
6843 X509_free(crt);
6844 return ret;
6845}
6846
Emeric Brunba841a12014-04-30 17:05:08 +02006847/* binary, returns serial of certificate in a binary chunk.
6848 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6849 * should be use.
6850 */
Willy Tarreau8d598402012-10-22 17:58:39 +02006851static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006852smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau8d598402012-10-22 17:58:39 +02006853{
Emeric Brunba841a12014-04-30 17:05:08 +02006854 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Willy Tarreau8d598402012-10-22 17:58:39 +02006855 X509 *crt = NULL;
6856 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006857 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006858 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006859 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006860
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006861 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006862 if (!conn || conn->xprt != &ssl_sock)
Willy Tarreau8d598402012-10-22 17:58:39 +02006863 return 0;
6864
Olivier Houchard66ab4982019-02-26 18:37:15 +01006865 ctx = conn->xprt_ctx;
6866
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006867 if (!(conn->flags & CO_FL_CONNECTED)) {
Willy Tarreau8d598402012-10-22 17:58:39 +02006868 smp->flags |= SMP_F_MAY_CHANGE;
6869 return 0;
6870 }
6871
Emeric Brunba841a12014-04-30 17:05:08 +02006872 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006873 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006874 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006875 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006876
Willy Tarreau8d598402012-10-22 17:58:39 +02006877 if (!crt)
6878 goto out;
6879
Willy Tarreau47ca5452012-12-23 20:22:19 +01006880 smp_trash = get_trash_chunk();
Willy Tarreau8d598402012-10-22 17:58:39 +02006881 if (ssl_sock_get_serial(crt, smp_trash) <= 0)
6882 goto out;
6883
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006884 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006885 smp->data.type = SMP_T_BIN;
Willy Tarreau8d598402012-10-22 17:58:39 +02006886 ret = 1;
6887out:
Emeric Brunba841a12014-04-30 17:05:08 +02006888 /* SSL_get_peer_certificate, it increase X509 * ref count */
6889 if (cert_peer && crt)
Willy Tarreau8d598402012-10-22 17:58:39 +02006890 X509_free(crt);
6891 return ret;
6892}
Emeric Brune64aef12012-09-21 13:15:06 +02006893
Emeric Brunba841a12014-04-30 17:05:08 +02006894/* binary, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk.
6895 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6896 * should be use.
6897 */
James Votha051b4a2013-05-14 20:37:59 +02006898static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006899smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
James Votha051b4a2013-05-14 20:37:59 +02006900{
Emeric Brunba841a12014-04-30 17:05:08 +02006901 int cert_peer = (kw[4] == 'c') ? 1 : 0;
James Votha051b4a2013-05-14 20:37:59 +02006902 X509 *crt = NULL;
6903 const EVP_MD *digest;
6904 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006905 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006906 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006907 struct ssl_sock_ctx *ctx;
James Votha051b4a2013-05-14 20:37:59 +02006908
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006909 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006910 if (!conn || conn->xprt != &ssl_sock)
6911 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006912 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006913
6914 if (!(conn->flags & CO_FL_CONNECTED)) {
James Votha051b4a2013-05-14 20:37:59 +02006915 smp->flags |= SMP_F_MAY_CHANGE;
6916 return 0;
6917 }
6918
Emeric Brunba841a12014-04-30 17:05:08 +02006919 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006920 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006921 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006922 crt = SSL_get_certificate(ctx->ssl);
James Votha051b4a2013-05-14 20:37:59 +02006923 if (!crt)
6924 goto out;
6925
6926 smp_trash = get_trash_chunk();
6927 digest = EVP_sha1();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02006928 X509_digest(crt, digest, (unsigned char *) smp_trash->area,
6929 (unsigned int *)&smp_trash->data);
James Votha051b4a2013-05-14 20:37:59 +02006930
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006931 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006932 smp->data.type = SMP_T_BIN;
James Votha051b4a2013-05-14 20:37:59 +02006933 ret = 1;
6934out:
Emeric Brunba841a12014-04-30 17:05:08 +02006935 /* SSL_get_peer_certificate, it increase X509 * ref count */
6936 if (cert_peer && crt)
James Votha051b4a2013-05-14 20:37:59 +02006937 X509_free(crt);
6938 return ret;
6939}
6940
Emeric Brunba841a12014-04-30 17:05:08 +02006941/* string, returns certificate's notafter date in ASN1_UTCTIME format.
6942 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6943 * should be use.
6944 */
Emeric Brunce5ad802012-10-22 14:11:22 +02006945static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006946smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02006947{
Emeric Brunba841a12014-04-30 17:05:08 +02006948 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02006949 X509 *crt = NULL;
6950 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006951 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006952 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006953 struct ssl_sock_ctx *ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02006954
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02006955 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006956 if (!conn || conn->xprt != &ssl_sock)
6957 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006958 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006959
6960 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02006961 smp->flags |= SMP_F_MAY_CHANGE;
6962 return 0;
6963 }
6964
Emeric Brunba841a12014-04-30 17:05:08 +02006965 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01006966 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02006967 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01006968 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02006969 if (!crt)
6970 goto out;
6971
Willy Tarreau47ca5452012-12-23 20:22:19 +01006972 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08006973 if (ssl_sock_get_time(X509_getm_notAfter(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02006974 goto out;
6975
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02006976 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02006977 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02006978 ret = 1;
6979out:
Emeric Brunba841a12014-04-30 17:05:08 +02006980 /* SSL_get_peer_certificate, it increase X509 * ref count */
6981 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02006982 X509_free(crt);
6983 return ret;
6984}
6985
Emeric Brunba841a12014-04-30 17:05:08 +02006986/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's issuer
6987 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
6988 * should be use.
6989 */
Emeric Brun87855892012-10-17 17:39:35 +02006990static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02006991smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02006992{
Emeric Brunba841a12014-04-30 17:05:08 +02006993 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02006994 X509 *crt = NULL;
6995 X509_NAME *name;
6996 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02006997 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02006998 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01006999 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007000
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007001 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007002 if (!conn || conn->xprt != &ssl_sock)
7003 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007004 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007005
7006 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007007 smp->flags |= SMP_F_MAY_CHANGE;
7008 return 0;
7009 }
7010
Emeric Brunba841a12014-04-30 17:05:08 +02007011 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007012 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007013 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007014 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007015 if (!crt)
7016 goto out;
7017
7018 name = X509_get_issuer_name(crt);
7019 if (!name)
7020 goto out;
7021
Willy Tarreau47ca5452012-12-23 20:22:19 +01007022 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007023 if (args && args[0].type == ARGT_STR) {
7024 int pos = 1;
7025
7026 if (args[1].type == ARGT_SINT)
7027 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007028
7029 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7030 goto out;
7031 }
7032 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7033 goto out;
7034
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007035 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007036 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007037 ret = 1;
7038out:
Emeric Brunba841a12014-04-30 17:05:08 +02007039 /* SSL_get_peer_certificate, it increase X509 * ref count */
7040 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007041 X509_free(crt);
7042 return ret;
7043}
7044
Emeric Brunba841a12014-04-30 17:05:08 +02007045/* string, returns notbefore date in ASN1_UTCTIME format.
7046 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7047 * should be use.
7048 */
Emeric Brunce5ad802012-10-22 14:11:22 +02007049static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007050smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunce5ad802012-10-22 14:11:22 +02007051{
Emeric Brunba841a12014-04-30 17:05:08 +02007052 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brunce5ad802012-10-22 14:11:22 +02007053 X509 *crt = NULL;
7054 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007055 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007056 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007057 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007058
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007059 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007060 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunce5ad802012-10-22 14:11:22 +02007061 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007062 ctx = conn->xprt_ctx;
Emeric Brunce5ad802012-10-22 14:11:22 +02007063
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007064 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunce5ad802012-10-22 14:11:22 +02007065 smp->flags |= SMP_F_MAY_CHANGE;
7066 return 0;
7067 }
7068
Emeric Brunba841a12014-04-30 17:05:08 +02007069 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007070 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007071 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007072 crt = SSL_get_certificate(ctx->ssl);
Emeric Brunce5ad802012-10-22 14:11:22 +02007073 if (!crt)
7074 goto out;
7075
Willy Tarreau47ca5452012-12-23 20:22:19 +01007076 smp_trash = get_trash_chunk();
Rosen Penev68185952018-12-14 08:47:02 -08007077 if (ssl_sock_get_time(X509_getm_notBefore(crt), smp_trash) <= 0)
Emeric Brunce5ad802012-10-22 14:11:22 +02007078 goto out;
7079
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007080 smp->data.u.str = *smp_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007081 smp->data.type = SMP_T_STR;
Emeric Brunce5ad802012-10-22 14:11:22 +02007082 ret = 1;
7083out:
Emeric Brunba841a12014-04-30 17:05:08 +02007084 /* SSL_get_peer_certificate, it increase X509 * ref count */
7085 if (cert_peer && crt)
Emeric Brunce5ad802012-10-22 14:11:22 +02007086 X509_free(crt);
7087 return ret;
7088}
7089
Emeric Brunba841a12014-04-30 17:05:08 +02007090/* string, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. of certificate's subject
7091 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7092 * should be use.
7093 */
Emeric Brun87855892012-10-17 17:39:35 +02007094static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007095smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun87855892012-10-17 17:39:35 +02007096{
Emeric Brunba841a12014-04-30 17:05:08 +02007097 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun87855892012-10-17 17:39:35 +02007098 X509 *crt = NULL;
7099 X509_NAME *name;
7100 int ret = 0;
Willy Tarreau83061a82018-07-13 11:56:34 +02007101 struct buffer *smp_trash;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007102 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007103 struct ssl_sock_ctx *ctx;
Emeric Brun87855892012-10-17 17:39:35 +02007104
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007105 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007106 if (!conn || conn->xprt != &ssl_sock)
7107 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007108 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007109
7110 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun87855892012-10-17 17:39:35 +02007111 smp->flags |= SMP_F_MAY_CHANGE;
7112 return 0;
7113 }
7114
Emeric Brunba841a12014-04-30 17:05:08 +02007115 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007116 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007117 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007118 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun87855892012-10-17 17:39:35 +02007119 if (!crt)
7120 goto out;
7121
7122 name = X509_get_subject_name(crt);
7123 if (!name)
7124 goto out;
7125
Willy Tarreau47ca5452012-12-23 20:22:19 +01007126 smp_trash = get_trash_chunk();
Emeric Brun87855892012-10-17 17:39:35 +02007127 if (args && args[0].type == ARGT_STR) {
7128 int pos = 1;
7129
7130 if (args[1].type == ARGT_SINT)
7131 pos = args[1].data.sint;
Emeric Brun87855892012-10-17 17:39:35 +02007132
7133 if (ssl_sock_get_dn_entry(name, &args[0].data.str, pos, smp_trash) <= 0)
7134 goto out;
7135 }
7136 else if (ssl_sock_get_dn_oneline(name, smp_trash) <= 0)
7137 goto out;
7138
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007139 smp->data.type = SMP_T_STR;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007140 smp->data.u.str = *smp_trash;
Emeric Brun87855892012-10-17 17:39:35 +02007141 ret = 1;
7142out:
Emeric Brunba841a12014-04-30 17:05:08 +02007143 /* SSL_get_peer_certificate, it increase X509 * ref count */
7144 if (cert_peer && crt)
Emeric Brun87855892012-10-17 17:39:35 +02007145 X509_free(crt);
7146 return ret;
7147}
Emeric Brun9143d372012-12-20 15:44:16 +01007148
7149/* integer, returns true if current session use a client certificate */
7150static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007151smp_fetch_ssl_c_used(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun9143d372012-12-20 15:44:16 +01007152{
7153 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007154 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007155 struct ssl_sock_ctx *ctx;
Emeric Brun9143d372012-12-20 15:44:16 +01007156
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007157 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007158 if (!conn || conn->xprt != &ssl_sock)
7159 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007160 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007161
7162 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun9143d372012-12-20 15:44:16 +01007163 smp->flags |= SMP_F_MAY_CHANGE;
7164 return 0;
7165 }
7166
7167 /* SSL_get_peer_certificate returns a ptr on allocated X509 struct */
Olivier Houchard66ab4982019-02-26 18:37:15 +01007168 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brun9143d372012-12-20 15:44:16 +01007169 if (crt) {
7170 X509_free(crt);
7171 }
7172
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007173 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007174 smp->data.u.sint = (crt != NULL);
Emeric Brun9143d372012-12-20 15:44:16 +01007175 return 1;
7176}
7177
Emeric Brunba841a12014-04-30 17:05:08 +02007178/* integer, returns the certificate version
7179 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7180 * should be use.
7181 */
Emeric Bruna7359fd2012-10-17 15:03:11 +02007182static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007183smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007184{
Emeric Brunba841a12014-04-30 17:05:08 +02007185 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007186 X509 *crt;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007187 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007188 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007189
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007190 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007191 if (!conn || conn->xprt != &ssl_sock)
Emeric Bruna7359fd2012-10-17 15:03:11 +02007192 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007193 ctx = conn->xprt_ctx;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007194
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007195 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Bruna7359fd2012-10-17 15:03:11 +02007196 smp->flags |= SMP_F_MAY_CHANGE;
7197 return 0;
7198 }
7199
Emeric Brunba841a12014-04-30 17:05:08 +02007200 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007201 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007202 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007203 crt = SSL_get_certificate(ctx->ssl);
Emeric Bruna7359fd2012-10-17 15:03:11 +02007204 if (!crt)
7205 return 0;
7206
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007207 smp->data.u.sint = (unsigned int)(1 + X509_get_version(crt));
Emeric Brunba841a12014-04-30 17:05:08 +02007208 /* SSL_get_peer_certificate increase X509 * ref count */
7209 if (cert_peer)
7210 X509_free(crt);
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007211 smp->data.type = SMP_T_SINT;
Emeric Bruna7359fd2012-10-17 15:03:11 +02007212
7213 return 1;
7214}
7215
Emeric Brunba841a12014-04-30 17:05:08 +02007216/* string, returns the certificate's signature algorithm.
7217 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7218 * should be use.
7219 */
Emeric Brun7f56e742012-10-19 18:15:40 +02007220static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007221smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun7f56e742012-10-19 18:15:40 +02007222{
Emeric Brunba841a12014-04-30 17:05:08 +02007223 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun7f56e742012-10-19 18:15:40 +02007224 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007225 __OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
Emeric Brun7f56e742012-10-19 18:15:40 +02007226 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007227 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007228 struct ssl_sock_ctx *ctx;
Emeric Brun7f56e742012-10-19 18:15:40 +02007229
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007230 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007231 if (!conn || conn->xprt != &ssl_sock)
7232 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007233 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007234
7235 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun7f56e742012-10-19 18:15:40 +02007236 smp->flags |= SMP_F_MAY_CHANGE;
7237 return 0;
7238 }
7239
Emeric Brunba841a12014-04-30 17:05:08 +02007240 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007241 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007242 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007243 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun7f56e742012-10-19 18:15:40 +02007244 if (!crt)
7245 return 0;
7246
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007247 X509_ALGOR_get0(&algorithm, NULL, NULL, X509_get0_tbs_sigalg(crt));
7248 nid = OBJ_obj2nid(algorithm);
Emeric Brun7f56e742012-10-19 18:15:40 +02007249
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007250 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7251 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007252 /* SSL_get_peer_certificate increase X509 * ref count */
7253 if (cert_peer)
7254 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007255 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007256 }
Emeric Brun7f56e742012-10-19 18:15:40 +02007257
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007258 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007259 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007260 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007261 /* SSL_get_peer_certificate increase X509 * ref count */
7262 if (cert_peer)
7263 X509_free(crt);
Emeric Brun7f56e742012-10-19 18:15:40 +02007264
7265 return 1;
7266}
7267
Emeric Brunba841a12014-04-30 17:05:08 +02007268/* string, returns the certificate's key algorithm.
7269 * The 5th keyword char is used to know if SSL_get_certificate or SSL_get_peer_certificate
7270 * should be use.
7271 */
Emeric Brun521a0112012-10-22 12:22:55 +02007272static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007273smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun521a0112012-10-22 12:22:55 +02007274{
Emeric Brunba841a12014-04-30 17:05:08 +02007275 int cert_peer = (kw[4] == 'c') ? 1 : 0;
Emeric Brun521a0112012-10-22 12:22:55 +02007276 X509 *crt;
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007277 ASN1_OBJECT *algorithm;
Emeric Brun521a0112012-10-22 12:22:55 +02007278 int nid;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007279 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007280 struct ssl_sock_ctx *ctx;
Emeric Brun521a0112012-10-22 12:22:55 +02007281
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007282 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007283 if (!conn || conn->xprt != &ssl_sock)
7284 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007285 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007286
7287 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brun521a0112012-10-22 12:22:55 +02007288 smp->flags |= SMP_F_MAY_CHANGE;
7289 return 0;
7290 }
7291
Emeric Brunba841a12014-04-30 17:05:08 +02007292 if (cert_peer)
Olivier Houchard66ab4982019-02-26 18:37:15 +01007293 crt = SSL_get_peer_certificate(ctx->ssl);
Emeric Brunba841a12014-04-30 17:05:08 +02007294 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007295 crt = SSL_get_certificate(ctx->ssl);
Emeric Brun521a0112012-10-22 12:22:55 +02007296 if (!crt)
7297 return 0;
7298
Dirkjan Bussink1866d6d2016-08-29 13:26:37 +02007299 X509_PUBKEY_get0_param(&algorithm, NULL, NULL, NULL, X509_get_X509_PUBKEY(crt));
7300 nid = OBJ_obj2nid(algorithm);
Emeric Brun521a0112012-10-22 12:22:55 +02007301
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007302 smp->data.u.str.area = (char *)OBJ_nid2sn(nid);
7303 if (!smp->data.u.str.area) {
Emeric Brunba841a12014-04-30 17:05:08 +02007304 /* SSL_get_peer_certificate increase X509 * ref count */
7305 if (cert_peer)
7306 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007307 return 0;
Emeric Brun9bf3ba22013-10-07 14:31:44 +02007308 }
Emeric Brun521a0112012-10-22 12:22:55 +02007309
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007310 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007311 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007312 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brunba841a12014-04-30 17:05:08 +02007313 if (cert_peer)
7314 X509_free(crt);
Emeric Brun521a0112012-10-22 12:22:55 +02007315
7316 return 1;
7317}
7318
Emeric Brun645ae792014-04-30 14:21:06 +02007319/* boolean, returns true if front conn. transport layer is SSL.
7320 * This function is also usable on backend conn if the fetch keyword 5th
7321 * char is 'b'.
7322 */
Willy Tarreau7875d092012-09-10 08:20:03 +02007323static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007324smp_fetch_ssl_fc(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007325{
Emeric Bruneb8def92018-02-19 15:59:48 +01007326 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7327 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007328
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007329 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007330 smp->data.u.sint = (conn && conn->xprt == &ssl_sock);
Willy Tarreau7875d092012-09-10 08:20:03 +02007331 return 1;
7332}
7333
Emeric Brun2525b6b2012-10-18 15:59:43 +02007334/* boolean, returns true if client present a SNI */
Willy Tarreau7875d092012-09-10 08:20:03 +02007335static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007336smp_fetch_ssl_fc_has_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007337{
7338#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007339 struct connection *conn = objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007340 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007341
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007342 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007343 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007344 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007345 SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name) != NULL;
Willy Tarreau7875d092012-09-10 08:20:03 +02007346 return 1;
7347#else
7348 return 0;
7349#endif
7350}
7351
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007352/* boolean, returns true if client session has been resumed.
7353 * This function is also usable on backend conn if the fetch keyword 5th
7354 * char is 'b'.
7355 */
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007356static int
7357smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const char *kw, void *private)
7358{
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007359 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7360 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007361 struct ssl_sock_ctx *ctx = conn ? conn->xprt_ctx : NULL;
Emeric Brun74f7ffa2018-02-19 16:14:12 +01007362
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007363
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007364 smp->data.type = SMP_T_BOOL;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007365 smp->data.u.sint = (conn && conn->xprt == &ssl_sock) &&
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007366 conn->xprt_ctx &&
Olivier Houchard66ab4982019-02-26 18:37:15 +01007367 SSL_session_reused(ctx->ssl);
Nenad Merdanovic26ea8222015-05-18 02:28:57 +02007368 return 1;
7369}
7370
Emeric Brun645ae792014-04-30 14:21:06 +02007371/* string, returns the used cipher if front conn. transport layer is SSL.
7372 * This function is also usable on backend conn if the fetch keyword 5th
7373 * char is 'b'.
7374 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007375static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007376smp_fetch_ssl_fc_cipher(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007377{
Emeric Bruneb8def92018-02-19 15:59:48 +01007378 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7379 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007380 struct ssl_sock_ctx *ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007381
Willy Tarreaube508f12016-03-10 11:47:01 +01007382 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007383 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007384 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007385 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007386
Olivier Houchard66ab4982019-02-26 18:37:15 +01007387 smp->data.u.str.area = (char *)SSL_get_cipher_name(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007388 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007389 return 0;
7390
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007391 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007392 smp->flags |= SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007393 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007394
7395 return 1;
7396}
7397
Emeric Brun645ae792014-04-30 14:21:06 +02007398/* integer, returns the algoritm's keysize if front conn. transport layer
7399 * is SSL.
7400 * This function is also usable on backend conn if the fetch keyword 5th
7401 * char is 'b'.
7402 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007403static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007404smp_fetch_ssl_fc_alg_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007405{
Emeric Bruneb8def92018-02-19 15:59:48 +01007406 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7407 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007408 struct ssl_sock_ctx *ctx;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007409 int sint;
Willy Tarreaube508f12016-03-10 11:47:01 +01007410
Emeric Brun589fcad2012-10-16 14:13:26 +02007411 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007412 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Emeric Brun589fcad2012-10-16 14:13:26 +02007413 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007414 ctx = conn->xprt_ctx;
Emeric Brun589fcad2012-10-16 14:13:26 +02007415
Olivier Houchard66ab4982019-02-26 18:37:15 +01007416 if (!SSL_get_cipher_bits(ctx->ssl, &sint))
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007417 return 0;
7418
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007419 smp->data.u.sint = sint;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007420 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007421
7422 return 1;
7423}
7424
Emeric Brun645ae792014-04-30 14:21:06 +02007425/* integer, returns the used keysize if front conn. transport layer is SSL.
7426 * This function is also usable on backend conn if the fetch keyword 5th
7427 * char is 'b'.
7428 */
Emeric Brun589fcad2012-10-16 14:13:26 +02007429static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007430smp_fetch_ssl_fc_use_keysize(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007431{
Emeric Bruneb8def92018-02-19 15:59:48 +01007432 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7433 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007434 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007435
Emeric Brun589fcad2012-10-16 14:13:26 +02007436 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007437 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7438 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007439 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007440
Olivier Houchard66ab4982019-02-26 18:37:15 +01007441 smp->data.u.sint = (unsigned int)SSL_get_cipher_bits(ctx->ssl, NULL);
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007442 if (!smp->data.u.sint)
Emeric Brun589fcad2012-10-16 14:13:26 +02007443 return 0;
7444
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007445 smp->data.type = SMP_T_SINT;
Emeric Brun589fcad2012-10-16 14:13:26 +02007446
7447 return 1;
7448}
7449
Bernard Spil13c53f82018-02-15 13:34:58 +01007450#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau7875d092012-09-10 08:20:03 +02007451static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007452smp_fetch_ssl_fc_npn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007453{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007454 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007455 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007456
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007457 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007458 smp->data.type = SMP_T_STR;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007459
Olivier Houchard6b77f492018-11-22 18:18:29 +01007460 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7461 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007462 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7463 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007464 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007465
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007466 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007467 SSL_get0_next_proto_negotiated(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007468 (const unsigned char **)&smp->data.u.str.area,
7469 (unsigned *)&smp->data.u.str.data);
Willy Tarreaua33c6542012-10-15 13:19:06 +02007470
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007471 if (!smp->data.u.str.area)
Willy Tarreaua33c6542012-10-15 13:19:06 +02007472 return 0;
7473
7474 return 1;
Willy Tarreaua33c6542012-10-15 13:19:06 +02007475}
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02007476#endif
Willy Tarreaua33c6542012-10-15 13:19:06 +02007477
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01007478#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02007479static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007480smp_fetch_ssl_fc_alpn(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreauab861d32013-04-02 02:30:41 +02007481{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007482 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007483 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007484
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007485 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007486 smp->data.type = SMP_T_STR;
Willy Tarreauab861d32013-04-02 02:30:41 +02007487
Olivier Houchard6b77f492018-11-22 18:18:29 +01007488 conn = (kw[4] != 'b' ) ? objt_conn(smp->sess->origin) :
7489 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7490
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007491 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
Willy Tarreauab861d32013-04-02 02:30:41 +02007492 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007493 ctx = conn->xprt_ctx;
Willy Tarreauab861d32013-04-02 02:30:41 +02007494
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007495 smp->data.u.str.area = NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007496 SSL_get0_alpn_selected(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007497 (const unsigned char **)&smp->data.u.str.area,
7498 (unsigned *)&smp->data.u.str.data);
Willy Tarreauab861d32013-04-02 02:30:41 +02007499
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007500 if (!smp->data.u.str.area)
Willy Tarreauab861d32013-04-02 02:30:41 +02007501 return 0;
7502
7503 return 1;
7504}
7505#endif
7506
Emeric Brun645ae792014-04-30 14:21:06 +02007507/* string, returns the used protocol if front conn. transport layer is SSL.
7508 * This function is also usable on backend conn if the fetch keyword 5th
7509 * char is 'b'.
7510 */
Willy Tarreaua33c6542012-10-15 13:19:06 +02007511static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007512smp_fetch_ssl_fc_protocol(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brun589fcad2012-10-16 14:13:26 +02007513{
Emeric Bruneb8def92018-02-19 15:59:48 +01007514 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7515 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007516 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007517
Emeric Brun589fcad2012-10-16 14:13:26 +02007518 smp->flags = 0;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007519 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7520 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007521 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007522
Olivier Houchard66ab4982019-02-26 18:37:15 +01007523 smp->data.u.str.area = (char *)SSL_get_version(ctx->ssl);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007524 if (!smp->data.u.str.area)
Emeric Brun589fcad2012-10-16 14:13:26 +02007525 return 0;
7526
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007527 smp->data.type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007528 smp->flags = SMP_F_CONST;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007529 smp->data.u.str.data = strlen(smp->data.u.str.area);
Emeric Brun589fcad2012-10-16 14:13:26 +02007530
7531 return 1;
7532}
7533
Willy Tarreau87b09662015-04-03 00:22:06 +02007534/* binary, returns the SSL stream id if front conn. transport layer is SSL.
Emeric Brun645ae792014-04-30 14:21:06 +02007535 * This function is also usable on backend conn if the fetch keyword 5th
7536 * char is 'b'.
7537 */
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007538#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun589fcad2012-10-16 14:13:26 +02007539static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007540smp_fetch_ssl_fc_session_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunfe68f682012-10-16 14:59:28 +02007541{
Emeric Bruneb8def92018-02-19 15:59:48 +01007542 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7543 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
Willy Tarreaue237fe12016-03-10 17:05:28 +01007544 SSL_SESSION *ssl_sess;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007545 struct ssl_sock_ctx *ctx;
Willy Tarreaube508f12016-03-10 11:47:01 +01007546
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007547 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007548 smp->data.type = SMP_T_BIN;
Emeric Brunfe68f682012-10-16 14:59:28 +02007549
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007550 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7551 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007552 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007553
Olivier Houchard66ab4982019-02-26 18:37:15 +01007554 ssl_sess = SSL_get_session(ctx->ssl);
Willy Tarreau192252e2015-04-04 01:47:55 +02007555 if (!ssl_sess)
Emeric Brunfe68f682012-10-16 14:59:28 +02007556 return 0;
7557
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007558 smp->data.u.str.area = (char *)SSL_SESSION_get_id(ssl_sess,
7559 (unsigned int *)&smp->data.u.str.data);
7560 if (!smp->data.u.str.area || !smp->data.u.str.data)
Emeric Brunfe68f682012-10-16 14:59:28 +02007561 return 0;
7562
7563 return 1;
Emeric Brunfe68f682012-10-16 14:59:28 +02007564}
Patrick Hemmer41966772018-04-28 19:15:48 -04007565#endif
7566
Emeric Brunfe68f682012-10-16 14:59:28 +02007567
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007568#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmere0275472018-04-28 19:15:51 -04007569static int
Patrick Hemmer65674662019-06-04 08:13:03 -04007570smp_fetch_ssl_fc_random(const struct arg *args, struct sample *smp, const char *kw, void *private)
7571{
7572 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7573 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7574 struct buffer *data;
7575 struct ssl_sock_ctx *ctx;
7576
7577 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7578 return 0;
7579 ctx = conn->xprt_ctx;
7580
7581 data = get_trash_chunk();
7582 if (kw[7] == 'c')
7583 data->data = SSL_get_client_random(ctx->ssl,
7584 (unsigned char *) data->area,
7585 data->size);
7586 else
7587 data->data = SSL_get_server_random(ctx->ssl,
7588 (unsigned char *) data->area,
7589 data->size);
7590 if (!data->data)
7591 return 0;
7592
7593 smp->flags = 0;
7594 smp->data.type = SMP_T_BIN;
7595 smp->data.u.str = *data;
7596
7597 return 1;
7598}
7599
7600static int
Patrick Hemmere0275472018-04-28 19:15:51 -04007601smp_fetch_ssl_fc_session_key(const struct arg *args, struct sample *smp, const char *kw, void *private)
7602{
7603 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7604 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
7605 SSL_SESSION *ssl_sess;
Willy Tarreau83061a82018-07-13 11:56:34 +02007606 struct buffer *data;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007607 struct ssl_sock_ctx *ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007608
7609 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7610 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007611 ctx = conn->xprt_ctx;
Patrick Hemmere0275472018-04-28 19:15:51 -04007612
Olivier Houchard66ab4982019-02-26 18:37:15 +01007613 ssl_sess = SSL_get_session(ctx->ssl);
Patrick Hemmere0275472018-04-28 19:15:51 -04007614 if (!ssl_sess)
7615 return 0;
7616
7617 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007618 data->data = SSL_SESSION_get_master_key(ssl_sess,
7619 (unsigned char *) data->area,
7620 data->size);
7621 if (!data->data)
Patrick Hemmere0275472018-04-28 19:15:51 -04007622 return 0;
7623
7624 smp->flags = 0;
7625 smp->data.type = SMP_T_BIN;
7626 smp->data.u.str = *data;
7627
7628 return 1;
7629}
7630#endif
7631
Patrick Hemmer41966772018-04-28 19:15:48 -04007632#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Emeric Brunfe68f682012-10-16 14:59:28 +02007633static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007634smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw, void *private)
Willy Tarreau7875d092012-09-10 08:20:03 +02007635{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007636 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007637 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007638
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01007639 smp->flags = SMP_F_CONST;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007640 smp->data.type = SMP_T_STR;
Willy Tarreau7875d092012-09-10 08:20:03 +02007641
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007642 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007643 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7644 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007645 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007646
Olivier Houchard66ab4982019-02-26 18:37:15 +01007647 smp->data.u.str.area = (char *)SSL_get_servername(ctx->ssl, TLSEXT_NAMETYPE_host_name);
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007648 if (!smp->data.u.str.area)
Willy Tarreau3e394c92012-09-14 23:56:58 +02007649 return 0;
7650
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007651 smp->data.u.str.data = strlen(smp->data.u.str.area);
Willy Tarreau7875d092012-09-10 08:20:03 +02007652 return 1;
Willy Tarreau7875d092012-09-10 08:20:03 +02007653}
Patrick Hemmer41966772018-04-28 19:15:48 -04007654#endif
Willy Tarreau7875d092012-09-10 08:20:03 +02007655
David Sc1ad52e2014-04-08 18:48:47 -04007656static int
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007657smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
7658{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007659 struct connection *conn;
7660 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007661 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007662
7663 conn = objt_conn(smp->sess->origin);
7664 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7665 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007666 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007667
Olivier Houchard66ab4982019-02-26 18:37:15 +01007668 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007669 if (!capture)
7670 return 0;
7671
7672 smp->flags = SMP_F_CONST;
7673 smp->data.type = SMP_T_BIN;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007674 smp->data.u.str.area = capture->ciphersuite;
7675 smp->data.u.str.data = capture->ciphersuite_len;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007676 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007677}
7678
7679static int
7680smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *kw, void *private)
7681{
Willy Tarreau83061a82018-07-13 11:56:34 +02007682 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007683
7684 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7685 return 0;
7686
7687 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007688 dump_binary(data, smp->data.u.str.area, smp->data.u.str.data);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007689 smp->data.type = SMP_T_BIN;
7690 smp->data.u.str = *data;
7691 return 1;
7692}
7693
7694static int
7695smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
7696{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007697 struct connection *conn;
7698 struct ssl_capture *capture;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007699 struct ssl_sock_ctx *ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007700
7701 conn = objt_conn(smp->sess->origin);
7702 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7703 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007704 ctx = conn->xprt_ctx;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007705
Olivier Houchard66ab4982019-02-26 18:37:15 +01007706 capture = SSL_get_ex_data(ctx->ssl, ssl_capture_ptr_index);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007707 if (!capture)
7708 return 0;
7709
7710 smp->data.type = SMP_T_SINT;
7711 smp->data.u.sint = capture->xxh64;
7712 return 1;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007713}
7714
7715static int
7716smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
7717{
Willy Tarreau5db847a2019-05-09 14:13:35 +02007718#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL)
Willy Tarreau83061a82018-07-13 11:56:34 +02007719 struct buffer *data;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007720 int i;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007721
7722 if (!smp_fetch_ssl_fc_cl_bin(args, smp, kw, private))
7723 return 0;
7724
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007725 data = get_trash_chunk();
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007726 for (i = 0; i + 1 < smp->data.u.str.data; i += 2) {
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007727 const char *str;
7728 const SSL_CIPHER *cipher;
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007729 const unsigned char *bin = (const unsigned char *) smp->data.u.str.area + i;
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007730 uint16_t id = (bin[0] << 8) | bin[1];
7731#if defined(OPENSSL_IS_BORINGSSL)
7732 cipher = SSL_get_cipher_by_value(id);
7733#else
Willy Tarreaub7290772018-10-15 11:01:59 +02007734 struct connection *conn = __objt_conn(smp->sess->origin);
Olivier Houchard66ab4982019-02-26 18:37:15 +01007735 struct ssl_sock_ctx *ctx = conn->xprt_ctx;
7736 cipher = SSL_CIPHER_find(ctx->ssl, bin);
Emmanuel Hocdetddcde192017-09-01 17:32:08 +02007737#endif
7738 str = SSL_CIPHER_get_name(cipher);
7739 if (!str || strcmp(str, "(NONE)") == 0)
7740 chunk_appendf(data, "%sUNKNOWN(%04x)", i == 0 ? "" : ",", id);
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007741 else
7742 chunk_appendf(data, "%s%s", i == 0 ? "" : ",", str);
7743 }
7744 smp->data.type = SMP_T_STR;
7745 smp->data.u.str = *data;
7746 return 1;
7747#else
7748 return smp_fetch_ssl_fc_cl_xxh64(args, smp, kw, private);
7749#endif
7750}
7751
Willy Tarreau9a1ab082019-05-09 13:26:41 +02007752#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01007753static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007754smp_fetch_ssl_fc_unique_id(const struct arg *args, struct sample *smp, const char *kw, void *private)
David Sc1ad52e2014-04-08 18:48:47 -04007755{
Emeric Bruneb8def92018-02-19 15:59:48 +01007756 struct connection *conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
7757 smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
David Sc1ad52e2014-04-08 18:48:47 -04007758 int finished_len;
Willy Tarreau83061a82018-07-13 11:56:34 +02007759 struct buffer *finished_trash;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007760 struct ssl_sock_ctx *ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007761
7762 smp->flags = 0;
David Sc1ad52e2014-04-08 18:48:47 -04007763 if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
7764 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007765 ctx = conn->xprt_ctx;
David Sc1ad52e2014-04-08 18:48:47 -04007766
7767 if (!(conn->flags & CO_FL_CONNECTED)) {
7768 smp->flags |= SMP_F_MAY_CHANGE;
7769 return 0;
7770 }
7771
7772 finished_trash = get_trash_chunk();
Olivier Houchard66ab4982019-02-26 18:37:15 +01007773 if (!SSL_session_reused(ctx->ssl))
7774 finished_len = SSL_get_peer_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007775 finished_trash->area,
7776 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007777 else
Olivier Houchard66ab4982019-02-26 18:37:15 +01007778 finished_len = SSL_get_finished(ctx->ssl,
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007779 finished_trash->area,
7780 finished_trash->size);
David Sc1ad52e2014-04-08 18:48:47 -04007781
7782 if (!finished_len)
7783 return 0;
7784
Willy Tarreau843b7cb2018-07-13 10:54:26 +02007785 finished_trash->data = finished_len;
Thierry FOURNIER136f9d32015-08-19 09:07:19 +02007786 smp->data.u.str = *finished_trash;
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007787 smp->data.type = SMP_T_BIN;
David Sc1ad52e2014-04-08 18:48:47 -04007788
7789 return 1;
David Sc1ad52e2014-04-08 18:48:47 -04007790}
Patrick Hemmer41966772018-04-28 19:15:48 -04007791#endif
David Sc1ad52e2014-04-08 18:48:47 -04007792
Emeric Brun2525b6b2012-10-18 15:59:43 +02007793/* integer, returns the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007794static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007795smp_fetch_ssl_c_ca_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007796{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007797 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007798 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007799
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007800 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007801 if (!conn || conn->xprt != &ssl_sock)
7802 return 0;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007803 ctx = conn->xprt_ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007804
7805 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007806 smp->flags = SMP_F_MAY_CHANGE;
7807 return 0;
7808 }
7809
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007810 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007811 smp->data.u.sint = (unsigned long long int)SSL_SOCK_ST_TO_CA_ERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007812 smp->flags = 0;
7813
7814 return 1;
7815}
7816
Emeric Brun2525b6b2012-10-18 15:59:43 +02007817/* integer, returns the depth of the first verify error in CA chain of client certificate chain. */
Emeric Brunf282a812012-09-21 15:27:54 +02007818static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007819smp_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 +02007820{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007821 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007822 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007823
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007824 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007825 if (!conn || conn->xprt != &ssl_sock)
Emeric Brunf282a812012-09-21 15:27:54 +02007826 return 0;
7827
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007828 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007829 smp->flags = SMP_F_MAY_CHANGE;
7830 return 0;
7831 }
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007832 ctx = conn->xprt_ctx;
Emeric Brunf282a812012-09-21 15:27:54 +02007833
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007834 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007835 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CAEDEPTH(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007836 smp->flags = 0;
7837
7838 return 1;
7839}
7840
Emeric Brun2525b6b2012-10-18 15:59:43 +02007841/* integer, returns the first verify error on client certificate */
Emeric Brunf282a812012-09-21 15:27:54 +02007842static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007843smp_fetch_ssl_c_err(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunf282a812012-09-21 15:27:54 +02007844{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007845 struct connection *conn;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007846 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007847
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007848 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007849 if (!conn || conn->xprt != &ssl_sock)
7850 return 0;
7851
7852 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunf282a812012-09-21 15:27:54 +02007853 smp->flags = SMP_F_MAY_CHANGE;
7854 return 0;
7855 }
7856
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007857 ctx = conn->xprt_ctx;
7858
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007859 smp->data.type = SMP_T_SINT;
Olivier Houchard7b5fd1e2019-02-28 18:10:45 +01007860 smp->data.u.sint = (long long int)SSL_SOCK_ST_TO_CRTERROR(ctx->xprt_st);
Emeric Brunf282a812012-09-21 15:27:54 +02007861 smp->flags = 0;
7862
7863 return 1;
7864}
7865
Emeric Brun2525b6b2012-10-18 15:59:43 +02007866/* integer, returns the verify result on client cert */
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007867static int
Thierry FOURNIER0786d052015-05-11 15:42:45 +02007868smp_fetch_ssl_c_verify(const struct arg *args, struct sample *smp, const char *kw, void *private)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007869{
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007870 struct connection *conn;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007871 struct ssl_sock_ctx *ctx;
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007872
Thierry FOURNIER0a9a2b82015-05-11 15:20:49 +02007873 conn = objt_conn(smp->sess->origin);
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007874 if (!conn || conn->xprt != &ssl_sock)
7875 return 0;
7876
7877 if (!(conn->flags & CO_FL_CONNECTED)) {
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007878 smp->flags = SMP_F_MAY_CHANGE;
7879 return 0;
7880 }
7881
Willy Tarreaub363a1f2013-10-01 10:45:07 +02007882 if (!conn->xprt_ctx)
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007883 return 0;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007884 ctx = conn->xprt_ctx;
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007885
Thierry FOURNIER8c542ca2015-08-19 09:00:18 +02007886 smp->data.type = SMP_T_SINT;
Olivier Houchard66ab4982019-02-26 18:37:15 +01007887 smp->data.u.sint = (long long int)SSL_get_verify_result(ctx->ssl);
Emeric Brunbaf8ffb2012-09-21 15:27:20 +02007888 smp->flags = 0;
7889
7890 return 1;
7891}
7892
Emeric Brunfb510ea2012-10-05 12:00:26 +02007893/* parse the "ca-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007894static 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 +02007895{
7896 if (!*args[cur_arg + 1]) {
7897 if (err)
7898 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7899 return ERR_ALERT | ERR_FATAL;
7900 }
7901
Willy Tarreauef934602016-12-22 23:12:01 +01007902 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7903 memprintf(&conf->ca_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02007904 else
7905 memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02007906
Emeric Brund94b3fe2012-09-20 18:23:56 +02007907 return 0;
7908}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007909static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7910{
7911 return ssl_bind_parse_ca_file(args, cur_arg, px, &conf->ssl_conf, err);
7912}
Emeric Brund94b3fe2012-09-20 18:23:56 +02007913
Christopher Faulet31af49d2015-06-09 17:29:50 +02007914/* parse the "ca-sign-file" bind keyword */
7915static int bind_parse_ca_sign_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7916{
7917 if (!*args[cur_arg + 1]) {
7918 if (err)
7919 memprintf(err, "'%s' : missing CAfile path", args[cur_arg]);
7920 return ERR_ALERT | ERR_FATAL;
7921 }
7922
Willy Tarreauef934602016-12-22 23:12:01 +01007923 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
7924 memprintf(&conf->ca_sign_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Christopher Faulet31af49d2015-06-09 17:29:50 +02007925 else
7926 memprintf(&conf->ca_sign_file, "%s", args[cur_arg + 1]);
7927
7928 return 0;
7929}
7930
Bertrand Jacquinff13c062016-11-13 16:37:11 +00007931/* parse the "ca-sign-pass" bind keyword */
Christopher Faulet31af49d2015-06-09 17:29:50 +02007932static int bind_parse_ca_sign_pass(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7933{
7934 if (!*args[cur_arg + 1]) {
7935 if (err)
7936 memprintf(err, "'%s' : missing CAkey password", args[cur_arg]);
7937 return ERR_ALERT | ERR_FATAL;
7938 }
7939 memprintf(&conf->ca_sign_pass, "%s", args[cur_arg + 1]);
7940 return 0;
7941}
7942
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007943/* parse the "ciphers" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007944static 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 +02007945{
7946 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007947 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007948 return ERR_ALERT | ERR_FATAL;
7949 }
7950
Emeric Brun76d88952012-10-05 15:47:31 +02007951 free(conf->ciphers);
Willy Tarreau4348fad2012-09-20 16:48:07 +02007952 conf->ciphers = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007953 return 0;
7954}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01007955static int bind_parse_ciphers(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7956{
7957 return ssl_bind_parse_ciphers(args, cur_arg, px, &conf->ssl_conf, err);
7958}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007959
Emmanuel Hocdet839af572019-05-14 16:27:35 +02007960#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02007961/* parse the "ciphersuites" bind keyword */
7962static int ssl_bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
7963{
7964 if (!*args[cur_arg + 1]) {
7965 memprintf(err, "'%s' : missing cipher suite", args[cur_arg]);
7966 return ERR_ALERT | ERR_FATAL;
7967 }
7968
7969 free(conf->ciphersuites);
7970 conf->ciphersuites = strdup(args[cur_arg + 1]);
7971 return 0;
7972}
7973static int bind_parse_ciphersuites(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
7974{
7975 return ssl_bind_parse_ciphersuites(args, cur_arg, px, &conf->ssl_conf, err);
7976}
7977#endif
7978
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007979/* parse the "crt" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02007980static 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 +02007981{
Willy Tarreau38011032013-08-13 16:59:39 +02007982 char path[MAXPATHLEN];
Willy Tarreaub75d6922014-04-14 18:05:41 +02007983
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007984 if (!*args[cur_arg + 1]) {
Willy Tarreaueb6cead2012-09-20 19:43:14 +02007985 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02007986 return ERR_ALERT | ERR_FATAL;
7987 }
7988
Willy Tarreauef934602016-12-22 23:12:01 +01007989 if ((*args[cur_arg + 1] != '/' ) && global_ssl.crt_base) {
7990 if ((strlen(global_ssl.crt_base) + 1 + strlen(args[cur_arg + 1]) + 1) > MAXPATHLEN) {
Emeric Brunc8e8d122012-10-02 18:42:10 +02007991 memprintf(err, "'%s' : path too long", args[cur_arg]);
7992 return ERR_ALERT | ERR_FATAL;
7993 }
Willy Tarreauef934602016-12-22 23:12:01 +01007994 snprintf(path, sizeof(path), "%s/%s", global_ssl.crt_base, args[cur_arg + 1]);
Willy Tarreau03209342016-12-22 17:08:28 +01007995 if (ssl_sock_load_cert(path, conf, err) > 0)
Emeric Brunc8e8d122012-10-02 18:42:10 +02007996 return ERR_ALERT | ERR_FATAL;
7997
7998 return 0;
7999 }
8000
Willy Tarreau03209342016-12-22 17:08:28 +01008001 if (ssl_sock_load_cert(args[cur_arg + 1], conf, err) > 0)
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008002 return ERR_ALERT | ERR_FATAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008003
8004 return 0;
8005}
8006
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008007/* parse the "crt-list" bind keyword */
8008static int bind_parse_crt_list(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8009{
8010 if (!*args[cur_arg + 1]) {
8011 memprintf(err, "'%s' : missing certificate location", args[cur_arg]);
8012 return ERR_ALERT | ERR_FATAL;
8013 }
8014
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008015 if (ssl_sock_load_cert_list_file(args[cur_arg + 1], conf, px, err) > 0) {
Willy Tarreauad1731d2013-04-02 17:35:58 +02008016 memprintf(err, "'%s' : %s", args[cur_arg], *err);
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008017 return ERR_ALERT | ERR_FATAL;
Willy Tarreauad1731d2013-04-02 17:35:58 +02008018 }
Emmanuel Hocdetfe616562013-01-22 15:31:15 +01008019
8020 return 0;
8021}
8022
Emeric Brunfb510ea2012-10-05 12:00:26 +02008023/* parse the "crl-file" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008024static 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 +02008025{
Emeric Brun051cdab2012-10-02 19:25:50 +02008026#ifndef X509_V_FLAG_CRL_CHECK
8027 if (err)
8028 memprintf(err, "'%s' : library does not support CRL verify", args[cur_arg]);
8029 return ERR_ALERT | ERR_FATAL;
8030#else
Emeric Brund94b3fe2012-09-20 18:23:56 +02008031 if (!*args[cur_arg + 1]) {
8032 if (err)
8033 memprintf(err, "'%s' : missing CRLfile path", args[cur_arg]);
8034 return ERR_ALERT | ERR_FATAL;
8035 }
Emeric Brun2b58d042012-09-20 17:10:03 +02008036
Willy Tarreauef934602016-12-22 23:12:01 +01008037 if ((*args[cur_arg + 1] != '/') && global_ssl.ca_base)
8038 memprintf(&conf->crl_file, "%s/%s", global_ssl.ca_base, args[cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008039 else
8040 memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
Emeric Brunc8e8d122012-10-02 18:42:10 +02008041
Emeric Brun2b58d042012-09-20 17:10:03 +02008042 return 0;
Emeric Brun051cdab2012-10-02 19:25:50 +02008043#endif
Emeric Brun2b58d042012-09-20 17:10:03 +02008044}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008045static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8046{
8047 return ssl_bind_parse_crl_file(args, cur_arg, px, &conf->ssl_conf, err);
8048}
Emeric Brun2b58d042012-09-20 17:10:03 +02008049
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008050/* parse the "curves" bind keyword keyword */
8051static int ssl_bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8052{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008053#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
Emmanuel Hocdete7f2b732017-01-09 16:15:54 +01008054 if (!*args[cur_arg + 1]) {
8055 if (err)
8056 memprintf(err, "'%s' : missing curve suite", args[cur_arg]);
8057 return ERR_ALERT | ERR_FATAL;
8058 }
8059 conf->curves = strdup(args[cur_arg + 1]);
8060 return 0;
8061#else
8062 if (err)
8063 memprintf(err, "'%s' : library does not support curve suite", args[cur_arg]);
8064 return ERR_ALERT | ERR_FATAL;
8065#endif
8066}
8067static int bind_parse_curves(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8068{
8069 return ssl_bind_parse_curves(args, cur_arg, px, &conf->ssl_conf, err);
8070}
8071
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008072/* parse the "ecdhe" bind keyword keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008073static 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 +02008074{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008075#if HA_OPENSSL_VERSION_NUMBER < 0x0090800fL
Emeric Brun2b58d042012-09-20 17:10:03 +02008076 if (err)
8077 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (too old)", args[cur_arg]);
8078 return ERR_ALERT | ERR_FATAL;
8079#elif defined(OPENSSL_NO_ECDH)
8080 if (err)
8081 memprintf(err, "'%s' : library does not support elliptic curve Diffie-Hellman (disabled via OPENSSL_NO_ECDH)", args[cur_arg]);
8082 return ERR_ALERT | ERR_FATAL;
8083#else
8084 if (!*args[cur_arg + 1]) {
8085 if (err)
8086 memprintf(err, "'%s' : missing named curve", args[cur_arg]);
8087 return ERR_ALERT | ERR_FATAL;
8088 }
8089
8090 conf->ecdhe = strdup(args[cur_arg + 1]);
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008091
8092 return 0;
Emeric Brun2b58d042012-09-20 17:10:03 +02008093#endif
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008094}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008095static int bind_parse_ecdhe(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8096{
8097 return ssl_bind_parse_ecdhe(args, cur_arg, px, &conf->ssl_conf, err);
8098}
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008099
Bertrand Jacquinff13c062016-11-13 16:37:11 +00008100/* parse the "crt-ignore-err" and "ca-ignore-err" bind keywords */
Emeric Brun81c00f02012-09-21 14:31:21 +02008101static int bind_parse_ignore_err(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8102{
8103 int code;
8104 char *p = args[cur_arg + 1];
8105 unsigned long long *ignerr = &conf->crt_ignerr;
8106
8107 if (!*p) {
8108 if (err)
8109 memprintf(err, "'%s' : missing error IDs list", args[cur_arg]);
8110 return ERR_ALERT | ERR_FATAL;
8111 }
8112
8113 if (strcmp(args[cur_arg], "ca-ignore-err") == 0)
8114 ignerr = &conf->ca_ignerr;
8115
8116 if (strcmp(p, "all") == 0) {
8117 *ignerr = ~0ULL;
8118 return 0;
8119 }
8120
8121 while (p) {
8122 code = atoi(p);
8123 if ((code <= 0) || (code > 63)) {
8124 if (err)
8125 memprintf(err, "'%s' : ID '%d' out of range (1..63) in error IDs list '%s'",
8126 args[cur_arg], code, args[cur_arg + 1]);
8127 return ERR_ALERT | ERR_FATAL;
8128 }
8129 *ignerr |= 1ULL << code;
8130 p = strchr(p, ',');
8131 if (p)
8132 p++;
8133 }
8134
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008135 return 0;
8136}
8137
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008138/* parse tls_method_options "no-xxx" and "force-xxx" */
8139static int parse_tls_method_options(char *arg, struct tls_version_filter *methods, char **err)
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008140{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008141 uint16_t v;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008142 char *p;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008143 p = strchr(arg, '-');
8144 if (!p)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008145 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008146 p++;
8147 if (!strcmp(p, "sslv3"))
8148 v = CONF_SSLV3;
8149 else if (!strcmp(p, "tlsv10"))
8150 v = CONF_TLSV10;
8151 else if (!strcmp(p, "tlsv11"))
8152 v = CONF_TLSV11;
8153 else if (!strcmp(p, "tlsv12"))
8154 v = CONF_TLSV12;
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +02008155 else if (!strcmp(p, "tlsv13"))
8156 v = CONF_TLSV13;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008157 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008158 goto fail;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008159 if (!strncmp(arg, "no-", 3))
8160 methods->flags |= methodVersions[v].flag;
8161 else if (!strncmp(arg, "force-", 6))
8162 methods->min = methods->max = v;
8163 else
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008164 goto fail;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008165 return 0;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008166 fail:
8167 if (err)
8168 memprintf(err, "'%s' : option not implemented", arg);
8169 return ERR_ALERT | ERR_FATAL;
Emeric Brun2d0c4822012-10-02 13:45:20 +02008170}
8171
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008172static 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 +02008173{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008174 return parse_tls_method_options(args[cur_arg], &conf->ssl_conf.ssl_methods, err);
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008175}
8176
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008177static 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 +02008178{
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008179 return parse_tls_method_options(args[*cur_arg], &newsrv->ssl_ctx.methods, err);
8180}
8181
8182/* parse tls_method min/max: "ssl-min-ver" and "ssl-max-ver" */
8183static int parse_tls_method_minmax(char **args, int cur_arg, struct tls_version_filter *methods, char **err)
8184{
8185 uint16_t i, v = 0;
8186 char *argv = args[cur_arg + 1];
8187 if (!*argv) {
8188 if (err)
8189 memprintf(err, "'%s' : missing the ssl/tls version", args[cur_arg]);
8190 return ERR_ALERT | ERR_FATAL;
8191 }
8192 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
8193 if (!strcmp(argv, methodVersions[i].name))
8194 v = i;
8195 if (!v) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008196 if (err)
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008197 memprintf(err, "'%s' : unknown ssl/tls version", args[cur_arg + 1]);
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008198 return ERR_ALERT | ERR_FATAL;
8199 }
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008200 if (!strcmp("ssl-min-ver", args[cur_arg]))
8201 methods->min = v;
8202 else if (!strcmp("ssl-max-ver", args[cur_arg]))
8203 methods->max = v;
8204 else {
8205 if (err)
8206 memprintf(err, "'%s' : option not implemented", args[cur_arg]);
8207 return ERR_ALERT | ERR_FATAL;
8208 }
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008209 return 0;
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008210}
Emeric Brun2cb7ae52012-10-05 14:14:21 +02008211
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +02008212static int ssl_bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8213{
Willy Tarreau9a1ab082019-05-09 13:26:41 +02008214#if (HA_OPENSSL_VERSION_NUMBER < 0x10101000L) && !defined(OPENSSL_IS_BORINGSSL)
Christopher Faulet767a84b2017-11-24 16:50:31 +01008215 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 +02008216#endif
8217 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_methods, err);
8218}
8219
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008220static int bind_parse_tls_method_minmax(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8221{
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008222 return parse_tls_method_minmax(args, cur_arg, &conf->ssl_conf.ssl_methods, err);
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008223}
8224
8225static int srv_parse_tls_method_minmax(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8226{
8227 return parse_tls_method_minmax(args, *cur_arg, &newsrv->ssl_ctx.methods, err);
8228}
8229
Emeric Brun2d0c4822012-10-02 13:45:20 +02008230/* parse the "no-tls-tickets" bind keyword */
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008231static 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 +02008232{
Emeric Brun89675492012-10-05 13:48:26 +02008233 conf->ssl_options |= BC_SSL_O_NO_TLS_TICKETS;
Emeric Brun81c00f02012-09-21 14:31:21 +02008234 return 0;
8235}
Emeric Brun2d0c4822012-10-02 13:45:20 +02008236
Olivier Houchardc2aae742017-09-22 18:26:28 +02008237/* parse the "allow-0rtt" bind keyword */
8238static int ssl_bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8239{
8240 conf->early_data = 1;
8241 return 0;
8242}
8243
8244static int bind_parse_allow_0rtt(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8245{
Olivier Houchard9679ac92017-10-27 14:58:08 +02008246 conf->ssl_conf.early_data = 1;
Olivier Houchardc2aae742017-09-22 18:26:28 +02008247 return 0;
8248}
8249
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008250/* parse the "npn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008251static 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 +02008252{
Bernard Spil13c53f82018-02-15 13:34:58 +01008253#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008254 char *p1, *p2;
8255
8256 if (!*args[cur_arg + 1]) {
8257 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[cur_arg]);
8258 return ERR_ALERT | ERR_FATAL;
8259 }
8260
8261 free(conf->npn_str);
8262
Willy Tarreau3724da12016-02-12 17:11:12 +01008263 /* the NPN string is built as a suite of (<len> <name>)*,
8264 * so we reuse each comma to store the next <len> and need
8265 * one more for the end of the string.
8266 */
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008267 conf->npn_len = strlen(args[cur_arg + 1]) + 1;
Willy Tarreau3724da12016-02-12 17:11:12 +01008268 conf->npn_str = calloc(1, conf->npn_len + 1);
Willy Tarreau6c9a3d52012-10-18 18:57:14 +02008269 memcpy(conf->npn_str + 1, args[cur_arg + 1], conf->npn_len);
8270
8271 /* replace commas with the name length */
8272 p1 = conf->npn_str;
8273 p2 = p1 + 1;
8274 while (1) {
8275 p2 = memchr(p1 + 1, ',', conf->npn_str + conf->npn_len - (p1 + 1));
8276 if (!p2)
8277 p2 = p1 + 1 + strlen(p1 + 1);
8278
8279 if (p2 - (p1 + 1) > 255) {
8280 *p2 = '\0';
8281 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8282 return ERR_ALERT | ERR_FATAL;
8283 }
8284
8285 *p1 = p2 - (p1 + 1);
8286 p1 = p2;
8287
8288 if (!*p2)
8289 break;
8290
8291 *(p2++) = '\0';
8292 }
8293 return 0;
8294#else
8295 if (err)
8296 memprintf(err, "'%s' : library does not support TLS NPN extension", args[cur_arg]);
8297 return ERR_ALERT | ERR_FATAL;
8298#endif
8299}
8300
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008301static int bind_parse_npn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8302{
8303 return ssl_bind_parse_npn(args, cur_arg, px, &conf->ssl_conf, err);
8304}
8305
Willy Tarreauab861d32013-04-02 02:30:41 +02008306/* parse the "alpn" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008307static 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 +02008308{
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01008309#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Willy Tarreauab861d32013-04-02 02:30:41 +02008310 char *p1, *p2;
8311
8312 if (!*args[cur_arg + 1]) {
8313 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[cur_arg]);
8314 return ERR_ALERT | ERR_FATAL;
8315 }
8316
8317 free(conf->alpn_str);
8318
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008319 /* the ALPN string is built as a suite of (<len> <name>)*,
8320 * so we reuse each comma to store the next <len> and need
8321 * one more for the end of the string.
8322 */
Willy Tarreauab861d32013-04-02 02:30:41 +02008323 conf->alpn_len = strlen(args[cur_arg + 1]) + 1;
Marcoen Hirschbergbef60912016-02-12 17:05:24 +01008324 conf->alpn_str = calloc(1, conf->alpn_len + 1);
Willy Tarreauab861d32013-04-02 02:30:41 +02008325 memcpy(conf->alpn_str + 1, args[cur_arg + 1], conf->alpn_len);
8326
8327 /* replace commas with the name length */
8328 p1 = conf->alpn_str;
8329 p2 = p1 + 1;
8330 while (1) {
8331 p2 = memchr(p1 + 1, ',', conf->alpn_str + conf->alpn_len - (p1 + 1));
8332 if (!p2)
8333 p2 = p1 + 1 + strlen(p1 + 1);
8334
8335 if (p2 - (p1 + 1) > 255) {
8336 *p2 = '\0';
8337 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[cur_arg], p1 + 1);
8338 return ERR_ALERT | ERR_FATAL;
8339 }
8340
8341 *p1 = p2 - (p1 + 1);
8342 p1 = p2;
8343
8344 if (!*p2)
8345 break;
8346
8347 *(p2++) = '\0';
8348 }
8349 return 0;
8350#else
8351 if (err)
8352 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[cur_arg]);
8353 return ERR_ALERT | ERR_FATAL;
8354#endif
8355}
8356
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008357static int bind_parse_alpn(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8358{
8359 return ssl_bind_parse_alpn(args, cur_arg, px, &conf->ssl_conf, err);
8360}
8361
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008362/* parse the "ssl" bind keyword */
Willy Tarreau4348fad2012-09-20 16:48:07 +02008363static 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 +02008364{
Willy Tarreau71a8c7c2016-12-21 22:04:54 +01008365 conf->xprt = &ssl_sock;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008366 conf->is_ssl = 1;
Emeric Brun76d88952012-10-05 15:47:31 +02008367
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008368 if (global_ssl.listen_default_ciphers && !conf->ssl_conf.ciphers)
8369 conf->ssl_conf.ciphers = strdup(global_ssl.listen_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008370#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008371 if (global_ssl.listen_default_ciphersuites && !conf->ssl_conf.ciphersuites)
8372 conf->ssl_conf.ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
8373#endif
Emmanuel Hocdet4608ed92017-01-20 13:06:27 +01008374 conf->ssl_options |= global_ssl.listen_default_ssloptions;
Emmanuel Hocdet43664762017-08-09 18:26:20 +02008375 conf->ssl_conf.ssl_methods.flags |= global_ssl.listen_default_sslmethods.flags;
8376 if (!conf->ssl_conf.ssl_methods.min)
8377 conf->ssl_conf.ssl_methods.min = global_ssl.listen_default_sslmethods.min;
8378 if (!conf->ssl_conf.ssl_methods.max)
8379 conf->ssl_conf.ssl_methods.max = global_ssl.listen_default_sslmethods.max;
Emeric Brun76d88952012-10-05 15:47:31 +02008380
Willy Tarreau79eeafa2012-09-14 07:53:05 +02008381 return 0;
8382}
8383
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008384/* parse the "prefer-client-ciphers" bind keyword */
8385static int bind_parse_pcc(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8386{
8387 conf->ssl_options |= BC_SSL_O_PREF_CLIE_CIPH;
8388 return 0;
8389}
8390
Christopher Faulet31af49d2015-06-09 17:29:50 +02008391/* parse the "generate-certificates" bind keyword */
8392static int bind_parse_generate_certs(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8393{
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01008394#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Christopher Faulet31af49d2015-06-09 17:29:50 +02008395 conf->generate_certs = 1;
8396#else
8397 memprintf(err, "%sthis version of openssl cannot generate SSL certificates.\n",
8398 err && *err ? *err : "");
8399#endif
8400 return 0;
8401}
8402
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008403/* parse the "strict-sni" bind keyword */
8404static int bind_parse_strict_sni(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8405{
8406 conf->strict_sni = 1;
8407 return 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008408}
8409
8410/* parse the "tls-ticket-keys" bind keyword */
8411static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8412{
8413#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
8414 FILE *f;
8415 int i = 0;
8416 char thisline[LINESIZE];
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008417 struct tls_keys_ref *keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008418
8419 if (!*args[cur_arg + 1]) {
8420 if (err)
8421 memprintf(err, "'%s' : missing TLS ticket keys file path", args[cur_arg]);
8422 return ERR_ALERT | ERR_FATAL;
8423 }
8424
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008425 keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008426 if (keys_ref) {
8427 keys_ref->refcount++;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008428 conf->keys_ref = keys_ref;
8429 return 0;
8430 }
8431
Vincent Bernat02779b62016-04-03 13:48:43 +02008432 keys_ref = malloc(sizeof(*keys_ref));
Emeric Brun09852f72019-01-10 10:51:13 +01008433 if (!keys_ref) {
8434 if (err)
8435 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8436 return ERR_ALERT | ERR_FATAL;
8437 }
8438
Emeric Brun9e754772019-01-10 17:51:55 +01008439 keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key));
Emeric Brun09852f72019-01-10 10:51:13 +01008440 if (!keys_ref->tlskeys) {
8441 free(keys_ref);
8442 if (err)
8443 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8444 return ERR_ALERT | ERR_FATAL;
8445 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008446
8447 if ((f = fopen(args[cur_arg + 1], "r")) == NULL) {
Emeric Brun09852f72019-01-10 10:51:13 +01008448 free(keys_ref->tlskeys);
8449 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008450 if (err)
8451 memprintf(err, "'%s' : unable to load ssl tickets keys file", args[cur_arg+1]);
8452 return ERR_ALERT | ERR_FATAL;
8453 }
8454
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008455 keys_ref->filename = strdup(args[cur_arg + 1]);
Emeric Brun09852f72019-01-10 10:51:13 +01008456 if (!keys_ref->filename) {
8457 free(keys_ref->tlskeys);
8458 free(keys_ref);
8459 if (err)
8460 memprintf(err, "'%s' : allocation error", args[cur_arg+1]);
8461 return ERR_ALERT | ERR_FATAL;
8462 }
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008463
Emeric Brun9e754772019-01-10 17:51:55 +01008464 keys_ref->key_size_bits = 0;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008465 while (fgets(thisline, sizeof(thisline), f) != NULL) {
8466 int len = strlen(thisline);
Emeric Brun9e754772019-01-10 17:51:55 +01008467 int dec_size;
8468
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008469 /* Strip newline characters from the end */
8470 if(thisline[len - 1] == '\n')
8471 thisline[--len] = 0;
8472
8473 if(thisline[len - 1] == '\r')
8474 thisline[--len] = 0;
8475
Emeric Brun9e754772019-01-10 17:51:55 +01008476 dec_size = base64dec(thisline, len, (char *) (keys_ref->tlskeys + i % TLS_TICKETS_NO), sizeof(union tls_sess_key));
8477 if (dec_size < 0) {
Emeric Brun09852f72019-01-10 10:51:13 +01008478 free(keys_ref->filename);
8479 free(keys_ref->tlskeys);
8480 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008481 if (err)
8482 memprintf(err, "'%s' : unable to decode base64 key on line %d", args[cur_arg+1], i + 1);
mildis16aa0152016-06-22 17:46:29 +02008483 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008484 return ERR_ALERT | ERR_FATAL;
8485 }
Emeric Brun9e754772019-01-10 17:51:55 +01008486 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_128))) {
8487 keys_ref->key_size_bits = 128;
8488 }
8489 else if (!keys_ref->key_size_bits && (dec_size == sizeof(struct tls_sess_key_256))) {
8490 keys_ref->key_size_bits = 256;
8491 }
8492 else if (((dec_size != sizeof(struct tls_sess_key_128)) && (dec_size != sizeof(struct tls_sess_key_256)))
8493 || ((dec_size == sizeof(struct tls_sess_key_128) && (keys_ref->key_size_bits != 128)))
8494 || ((dec_size == sizeof(struct tls_sess_key_256) && (keys_ref->key_size_bits != 256)))) {
8495 free(keys_ref->filename);
8496 free(keys_ref->tlskeys);
8497 free(keys_ref);
8498 if (err)
8499 memprintf(err, "'%s' : wrong sized key on line %d", args[cur_arg+1], i + 1);
8500 fclose(f);
8501 return ERR_ALERT | ERR_FATAL;
8502 }
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008503 i++;
8504 }
8505
8506 if (i < TLS_TICKETS_NO) {
Emeric Brun09852f72019-01-10 10:51:13 +01008507 free(keys_ref->filename);
8508 free(keys_ref->tlskeys);
8509 free(keys_ref);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008510 if (err)
8511 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 +02008512 fclose(f);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008513 return ERR_ALERT | ERR_FATAL;
8514 }
8515
8516 fclose(f);
8517
8518 /* Use penultimate key for encryption, handle when TLS_TICKETS_NO = 1 */
Nenad Merdanovic17891152016-03-25 22:16:57 +01008519 i -= 2;
8520 keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008521 keys_ref->unique_id = -1;
Willy Tarreau17b4aa12018-07-17 10:05:32 +02008522 keys_ref->refcount = 1;
Christopher Faulet16f45c82018-02-16 11:23:49 +01008523 HA_RWLOCK_INIT(&keys_ref->lock);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008524 conf->keys_ref = keys_ref;
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008525
Nenad Merdanovic200b0fa2015-05-09 08:46:01 +02008526 LIST_ADD(&tlskeys_reference, &keys_ref->list);
8527
Nenad Merdanovic05552d42015-02-27 19:56:49 +01008528 return 0;
8529#else
8530 if (err)
8531 memprintf(err, "'%s' : TLS ticket callback extension not supported", args[cur_arg]);
8532 return ERR_ALERT | ERR_FATAL;
8533#endif /* SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB */
Emmanuel Hocdet65623372013-01-24 17:17:15 +01008534}
8535
Emeric Brund94b3fe2012-09-20 18:23:56 +02008536/* parse the "verify" bind keyword */
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008537static 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 +02008538{
8539 if (!*args[cur_arg + 1]) {
8540 if (err)
8541 memprintf(err, "'%s' : missing verify method", args[cur_arg]);
8542 return ERR_ALERT | ERR_FATAL;
8543 }
8544
8545 if (strcmp(args[cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008546 conf->verify = SSL_SOCK_VERIFY_NONE;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008547 else if (strcmp(args[cur_arg + 1], "optional") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008548 conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008549 else if (strcmp(args[cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008550 conf->verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brund94b3fe2012-09-20 18:23:56 +02008551 else {
8552 if (err)
8553 memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
8554 args[cur_arg], args[cur_arg + 1]);
8555 return ERR_ALERT | ERR_FATAL;
8556 }
8557
8558 return 0;
8559}
Emmanuel Hocdet98263292016-12-29 18:26:15 +01008560static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8561{
8562 return ssl_bind_parse_verify(args, cur_arg, px, &conf->ssl_conf, err);
8563}
Emeric Brund94b3fe2012-09-20 18:23:56 +02008564
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +02008565/* parse the "no-ca-names" bind keyword */
8566static int ssl_bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct ssl_bind_conf *conf, char **err)
8567{
8568 conf->no_ca_names = 1;
8569 return 0;
8570}
8571static int bind_parse_no_ca_names(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
8572{
8573 return ssl_bind_parse_no_ca_names(args, cur_arg, px, &conf->ssl_conf, err);
8574}
8575
Willy Tarreau92faadf2012-10-10 23:04:25 +02008576/************** "server" keywords ****************/
8577
Olivier Houchardc7566002018-11-20 23:33:50 +01008578/* parse the "npn" bind keyword */
8579static int srv_parse_npn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8580{
8581#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
8582 char *p1, *p2;
8583
8584 if (!*args[*cur_arg + 1]) {
8585 memprintf(err, "'%s' : missing the comma-delimited NPN protocol suite", args[*cur_arg]);
8586 return ERR_ALERT | ERR_FATAL;
8587 }
8588
8589 free(newsrv->ssl_ctx.npn_str);
8590
8591 /* the NPN string is built as a suite of (<len> <name>)*,
8592 * so we reuse each comma to store the next <len> and need
8593 * one more for the end of the string.
8594 */
8595 newsrv->ssl_ctx.npn_len = strlen(args[*cur_arg + 1]) + 1;
8596 newsrv->ssl_ctx.npn_str = calloc(1, newsrv->ssl_ctx.npn_len + 1);
8597 memcpy(newsrv->ssl_ctx.npn_str + 1, args[*cur_arg + 1],
8598 newsrv->ssl_ctx.npn_len);
8599
8600 /* replace commas with the name length */
8601 p1 = newsrv->ssl_ctx.npn_str;
8602 p2 = p1 + 1;
8603 while (1) {
8604 p2 = memchr(p1 + 1, ',', newsrv->ssl_ctx.npn_str +
8605 newsrv->ssl_ctx.npn_len - (p1 + 1));
8606 if (!p2)
8607 p2 = p1 + 1 + strlen(p1 + 1);
8608
8609 if (p2 - (p1 + 1) > 255) {
8610 *p2 = '\0';
8611 memprintf(err, "'%s' : NPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8612 return ERR_ALERT | ERR_FATAL;
8613 }
8614
8615 *p1 = p2 - (p1 + 1);
8616 p1 = p2;
8617
8618 if (!*p2)
8619 break;
8620
8621 *(p2++) = '\0';
8622 }
8623 return 0;
8624#else
8625 if (err)
8626 memprintf(err, "'%s' : library does not support TLS NPN extension", args[*cur_arg]);
8627 return ERR_ALERT | ERR_FATAL;
8628#endif
8629}
8630
Olivier Houchard92150142018-12-21 19:47:01 +01008631/* parse the "alpn" or the "check-alpn" server keyword */
Olivier Houchardc7566002018-11-20 23:33:50 +01008632static int srv_parse_alpn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8633{
8634#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
8635 char *p1, *p2;
Olivier Houchard92150142018-12-21 19:47:01 +01008636 char **alpn_str;
8637 int *alpn_len;
Olivier Houchardc7566002018-11-20 23:33:50 +01008638
Olivier Houchard92150142018-12-21 19:47:01 +01008639 if (*args[*cur_arg] == 'c') {
8640 alpn_str = &newsrv->check.alpn_str;
8641 alpn_len = &newsrv->check.alpn_len;
8642 } else {
8643 alpn_str = &newsrv->ssl_ctx.alpn_str;
8644 alpn_len = &newsrv->ssl_ctx.alpn_len;
8645
8646 }
Olivier Houchardc7566002018-11-20 23:33:50 +01008647 if (!*args[*cur_arg + 1]) {
8648 memprintf(err, "'%s' : missing the comma-delimited ALPN protocol suite", args[*cur_arg]);
8649 return ERR_ALERT | ERR_FATAL;
8650 }
8651
Olivier Houchard92150142018-12-21 19:47:01 +01008652 free(*alpn_str);
Olivier Houchardc7566002018-11-20 23:33:50 +01008653
8654 /* the ALPN string is built as a suite of (<len> <name>)*,
8655 * so we reuse each comma to store the next <len> and need
8656 * one more for the end of the string.
8657 */
Olivier Houchard92150142018-12-21 19:47:01 +01008658 *alpn_len = strlen(args[*cur_arg + 1]) + 1;
8659 *alpn_str = calloc(1, *alpn_len + 1);
8660 memcpy(*alpn_str + 1, args[*cur_arg + 1], *alpn_len);
Olivier Houchardc7566002018-11-20 23:33:50 +01008661
8662 /* replace commas with the name length */
Olivier Houchard92150142018-12-21 19:47:01 +01008663 p1 = *alpn_str;
Olivier Houchardc7566002018-11-20 23:33:50 +01008664 p2 = p1 + 1;
8665 while (1) {
Olivier Houchard92150142018-12-21 19:47:01 +01008666 p2 = memchr(p1 + 1, ',', *alpn_str + *alpn_len - (p1 + 1));
Olivier Houchardc7566002018-11-20 23:33:50 +01008667 if (!p2)
8668 p2 = p1 + 1 + strlen(p1 + 1);
8669
8670 if (p2 - (p1 + 1) > 255) {
8671 *p2 = '\0';
8672 memprintf(err, "'%s' : ALPN protocol name too long : '%s'", args[*cur_arg], p1 + 1);
8673 return ERR_ALERT | ERR_FATAL;
8674 }
8675
8676 *p1 = p2 - (p1 + 1);
8677 p1 = p2;
8678
8679 if (!*p2)
8680 break;
8681
8682 *(p2++) = '\0';
8683 }
8684 return 0;
8685#else
8686 if (err)
8687 memprintf(err, "'%s' : library does not support TLS ALPN extension", args[*cur_arg]);
8688 return ERR_ALERT | ERR_FATAL;
8689#endif
8690}
8691
Emeric Brunef42d922012-10-11 16:11:36 +02008692/* parse the "ca-file" server keyword */
8693static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8694{
8695 if (!*args[*cur_arg + 1]) {
8696 if (err)
8697 memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
8698 return ERR_ALERT | ERR_FATAL;
8699 }
8700
Willy Tarreauef934602016-12-22 23:12:01 +01008701 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8702 memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008703 else
8704 memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
8705
8706 return 0;
8707}
8708
Olivier Houchard9130a962017-10-17 17:33:43 +02008709/* parse the "check-sni" server keyword */
8710static int srv_parse_check_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8711{
8712 if (!*args[*cur_arg + 1]) {
8713 if (err)
8714 memprintf(err, "'%s' : missing SNI", args[*cur_arg]);
8715 return ERR_ALERT | ERR_FATAL;
8716 }
8717
8718 newsrv->check.sni = strdup(args[*cur_arg + 1]);
8719 if (!newsrv->check.sni) {
8720 memprintf(err, "'%s' : failed to allocate memory", args[*cur_arg]);
8721 return ERR_ALERT | ERR_FATAL;
8722 }
8723 return 0;
8724
8725}
8726
Willy Tarreau92faadf2012-10-10 23:04:25 +02008727/* parse the "check-ssl" server keyword */
8728static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8729{
8730 newsrv->check.use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008731 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8732 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008733#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008734 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8735 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8736#endif
Willy Tarreauef934602016-12-22 23:12:01 +01008737 newsrv->ssl_ctx.options |= global_ssl.connect_default_ssloptions;
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008738 newsrv->ssl_ctx.methods.flags |= global_ssl.connect_default_sslmethods.flags;
8739 if (!newsrv->ssl_ctx.methods.min)
8740 newsrv->ssl_ctx.methods.min = global_ssl.connect_default_sslmethods.min;
8741 if (!newsrv->ssl_ctx.methods.max)
8742 newsrv->ssl_ctx.methods.max = global_ssl.connect_default_sslmethods.max;
8743
Willy Tarreau92faadf2012-10-10 23:04:25 +02008744 return 0;
8745}
8746
8747/* parse the "ciphers" server keyword */
8748static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8749{
8750 if (!*args[*cur_arg + 1]) {
8751 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8752 return ERR_ALERT | ERR_FATAL;
8753 }
8754
8755 free(newsrv->ssl_ctx.ciphers);
8756 newsrv->ssl_ctx.ciphers = strdup(args[*cur_arg + 1]);
8757 return 0;
8758}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008759
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008760#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008761/* parse the "ciphersuites" server keyword */
8762static int srv_parse_ciphersuites(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8763{
8764 if (!*args[*cur_arg + 1]) {
8765 memprintf(err, "'%s' : missing cipher suite", args[*cur_arg]);
8766 return ERR_ALERT | ERR_FATAL;
8767 }
8768
8769 free(newsrv->ssl_ctx.ciphersuites);
8770 newsrv->ssl_ctx.ciphersuites = strdup(args[*cur_arg + 1]);
8771 return 0;
8772}
8773#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008774
Emeric Brunef42d922012-10-11 16:11:36 +02008775/* parse the "crl-file" server keyword */
8776static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8777{
8778#ifndef X509_V_FLAG_CRL_CHECK
8779 if (err)
8780 memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
8781 return ERR_ALERT | ERR_FATAL;
8782#else
8783 if (!*args[*cur_arg + 1]) {
8784 if (err)
8785 memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
8786 return ERR_ALERT | ERR_FATAL;
8787 }
8788
Willy Tarreauef934602016-12-22 23:12:01 +01008789 if ((*args[*cur_arg + 1] != '/') && global_ssl.ca_base)
8790 memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global_ssl.ca_base, args[*cur_arg + 1]);
Emeric Brunef42d922012-10-11 16:11:36 +02008791 else
8792 memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
8793
8794 return 0;
8795#endif
8796}
8797
Emeric Bruna7aa3092012-10-26 12:58:00 +02008798/* parse the "crt" server keyword */
8799static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8800{
8801 if (!*args[*cur_arg + 1]) {
8802 if (err)
8803 memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]);
8804 return ERR_ALERT | ERR_FATAL;
8805 }
8806
Willy Tarreauef934602016-12-22 23:12:01 +01008807 if ((*args[*cur_arg + 1] != '/') && global_ssl.crt_base)
Christopher Fauletff3a41e2017-11-23 09:13:32 +01008808 memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global_ssl.crt_base, args[*cur_arg + 1]);
Emeric Bruna7aa3092012-10-26 12:58:00 +02008809 else
8810 memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]);
8811
8812 return 0;
8813}
Emeric Brunef42d922012-10-11 16:11:36 +02008814
Frédéric Lécaille340ae602017-03-13 10:38:04 +01008815/* parse the "no-check-ssl" server keyword */
8816static int srv_parse_no_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8817{
8818 newsrv->check.use_ssl = 0;
8819 free(newsrv->ssl_ctx.ciphers);
8820 newsrv->ssl_ctx.ciphers = NULL;
8821 newsrv->ssl_ctx.options &= ~global_ssl.connect_default_ssloptions;
8822 return 0;
8823}
8824
Frédéric Lécaillee892c4c2017-03-13 12:08:01 +01008825/* parse the "no-send-proxy-v2-ssl" server keyword */
8826static int srv_parse_no_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8827{
8828 newsrv->pp_opts &= ~SRV_PP_V2;
8829 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8830 return 0;
8831}
8832
8833/* parse the "no-send-proxy-v2-ssl-cn" server keyword */
8834static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8835{
8836 newsrv->pp_opts &= ~SRV_PP_V2;
8837 newsrv->pp_opts &= ~SRV_PP_V2_SSL;
8838 newsrv->pp_opts &= ~SRV_PP_V2_SSL_CN;
8839 return 0;
8840}
8841
Frédéric Lécaillee381d762017-03-13 11:54:17 +01008842/* parse the "no-ssl" server keyword */
8843static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8844{
8845 newsrv->use_ssl = 0;
8846 free(newsrv->ssl_ctx.ciphers);
8847 newsrv->ssl_ctx.ciphers = NULL;
8848 return 0;
8849}
8850
Olivier Houchard522eea72017-11-03 16:27:47 +01008851/* parse the "allow-0rtt" server keyword */
8852static int srv_parse_allow_0rtt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8853{
8854 newsrv->ssl_ctx.options |= SRV_SSL_O_EARLY_DATA;
8855 return 0;
8856}
8857
Willy Tarreau2a3fb1c2015-02-05 16:47:07 +01008858/* parse the "no-ssl-reuse" server keyword */
8859static int srv_parse_no_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8860{
8861 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_REUSE;
8862 return 0;
8863}
8864
Emeric Brunf9c5c472012-10-11 15:28:34 +02008865/* parse the "no-tls-tickets" server keyword */
8866static int srv_parse_no_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8867{
8868 newsrv->ssl_ctx.options |= SRV_SSL_O_NO_TLS_TICKETS;
8869 return 0;
8870}
David Safb76832014-05-08 23:42:08 -04008871/* parse the "send-proxy-v2-ssl" server keyword */
8872static int srv_parse_send_proxy_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8873{
8874 newsrv->pp_opts |= SRV_PP_V2;
8875 newsrv->pp_opts |= SRV_PP_V2_SSL;
8876 return 0;
8877}
8878
8879/* parse the "send-proxy-v2-ssl-cn" server keyword */
8880static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8881{
8882 newsrv->pp_opts |= SRV_PP_V2;
8883 newsrv->pp_opts |= SRV_PP_V2_SSL;
8884 newsrv->pp_opts |= SRV_PP_V2_SSL_CN;
8885 return 0;
8886}
Emeric Brunf9c5c472012-10-11 15:28:34 +02008887
Willy Tarreau732eac42015-07-09 11:40:25 +02008888/* parse the "sni" server keyword */
8889static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8890{
8891#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
8892 memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
8893 return ERR_ALERT | ERR_FATAL;
8894#else
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008895 char *arg;
Willy Tarreau732eac42015-07-09 11:40:25 +02008896
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008897 arg = args[*cur_arg + 1];
8898 if (!*arg) {
Willy Tarreau732eac42015-07-09 11:40:25 +02008899 memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
8900 return ERR_ALERT | ERR_FATAL;
8901 }
8902
Frédéric Lécaille9a146de2017-03-20 14:54:41 +01008903 free(newsrv->sni_expr);
8904 newsrv->sni_expr = strdup(arg);
Willy Tarreau732eac42015-07-09 11:40:25 +02008905
Willy Tarreau732eac42015-07-09 11:40:25 +02008906 return 0;
8907#endif
8908}
8909
Willy Tarreau92faadf2012-10-10 23:04:25 +02008910/* parse the "ssl" server keyword */
8911static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8912{
8913 newsrv->use_ssl = 1;
Willy Tarreauef934602016-12-22 23:12:01 +01008914 if (global_ssl.connect_default_ciphers && !newsrv->ssl_ctx.ciphers)
8915 newsrv->ssl_ctx.ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +02008916#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02008917 if (global_ssl.connect_default_ciphersuites && !newsrv->ssl_ctx.ciphersuites)
8918 newsrv->ssl_ctx.ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
8919#endif
Willy Tarreau92faadf2012-10-10 23:04:25 +02008920 return 0;
8921}
8922
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008923/* parse the "ssl-reuse" server keyword */
8924static int srv_parse_ssl_reuse(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8925{
8926 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_REUSE;
8927 return 0;
8928}
8929
Frédéric Lécaille2cfcdbe2017-03-13 11:32:20 +01008930/* parse the "tls-tickets" server keyword */
8931static int srv_parse_tls_tickets(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8932{
8933 newsrv->ssl_ctx.options &= ~SRV_SSL_O_NO_TLS_TICKETS;
8934 return 0;
8935}
8936
Emeric Brunef42d922012-10-11 16:11:36 +02008937/* parse the "verify" server keyword */
8938static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8939{
8940 if (!*args[*cur_arg + 1]) {
8941 if (err)
8942 memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
8943 return ERR_ALERT | ERR_FATAL;
8944 }
8945
8946 if (strcmp(args[*cur_arg + 1], "none") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008947 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
Emeric Brunef42d922012-10-11 16:11:36 +02008948 else if (strcmp(args[*cur_arg + 1], "required") == 0)
Emeric Brun850efd52014-01-29 12:24:34 +01008949 newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
Emeric Brunef42d922012-10-11 16:11:36 +02008950 else {
8951 if (err)
8952 memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
8953 args[*cur_arg], args[*cur_arg + 1]);
8954 return ERR_ALERT | ERR_FATAL;
8955 }
8956
Evan Broderbe554312013-06-27 00:05:25 -07008957 return 0;
8958}
8959
8960/* parse the "verifyhost" server keyword */
8961static int srv_parse_verifyhost(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
8962{
8963 if (!*args[*cur_arg + 1]) {
8964 if (err)
8965 memprintf(err, "'%s' : missing hostname to verify against", args[*cur_arg]);
8966 return ERR_ALERT | ERR_FATAL;
8967 }
8968
Frédéric Lécaille273f3212017-03-13 15:52:01 +01008969 free(newsrv->ssl_ctx.verify_host);
Evan Broderbe554312013-06-27 00:05:25 -07008970 newsrv->ssl_ctx.verify_host = strdup(args[*cur_arg + 1]);
8971
Emeric Brunef42d922012-10-11 16:11:36 +02008972 return 0;
8973}
8974
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008975/* parse the "ssl-default-bind-options" keyword in global section */
8976static int ssl_parse_default_bind_options(char **args, int section_type, struct proxy *curpx,
8977 struct proxy *defpx, const char *file, int line,
8978 char **err) {
8979 int i = 1;
8980
8981 if (*(args[i]) == 0) {
8982 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
8983 return -1;
8984 }
8985 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02008986 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01008987 global_ssl.listen_default_ssloptions |= BC_SSL_O_NO_TLS_TICKETS;
Lukas Tribus53ae85c2017-05-04 15:45:40 +00008988 else if (!strcmp(args[i], "prefer-client-ciphers"))
8989 global_ssl.listen_default_ssloptions |= BC_SSL_O_PREF_CLIE_CIPH;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02008990 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
8991 if (!parse_tls_method_minmax(args, i, &global_ssl.listen_default_sslmethods, err))
8992 i++;
8993 else {
8994 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
8995 return -1;
8996 }
8997 }
8998 else if (parse_tls_method_options(args[i], &global_ssl.listen_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01008999 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9000 return -1;
9001 }
9002 i++;
9003 }
9004 return 0;
9005}
9006
9007/* parse the "ssl-default-server-options" keyword in global section */
9008static int ssl_parse_default_server_options(char **args, int section_type, struct proxy *curpx,
9009 struct proxy *defpx, const char *file, int line,
9010 char **err) {
9011 int i = 1;
9012
9013 if (*(args[i]) == 0) {
9014 memprintf(err, "global statement '%s' expects an option as an argument.", args[0]);
9015 return -1;
9016 }
9017 while (*(args[i])) {
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +02009018 if (!strcmp(args[i], "no-tls-tickets"))
Willy Tarreauef934602016-12-22 23:12:01 +01009019 global_ssl.connect_default_ssloptions |= SRV_SSL_O_NO_TLS_TICKETS;
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +02009020 else if (!strcmp(args[i], "ssl-min-ver") || !strcmp(args[i], "ssl-max-ver")) {
9021 if (!parse_tls_method_minmax(args, i, &global_ssl.connect_default_sslmethods, err))
9022 i++;
9023 else {
9024 memprintf(err, "%s on global statement '%s'.", *err, args[0]);
9025 return -1;
9026 }
9027 }
9028 else if (parse_tls_method_options(args[i], &global_ssl.connect_default_sslmethods, err)) {
Emeric Brun2c86cbf2014-10-30 15:56:50 +01009029 memprintf(err, "unknown option '%s' on global statement '%s'.", args[i], args[0]);
9030 return -1;
9031 }
9032 i++;
9033 }
9034 return 0;
9035}
9036
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009037/* parse the "ca-base" / "crt-base" keywords in global section.
9038 * Returns <0 on alert, >0 on warning, 0 on success.
9039 */
9040static int ssl_parse_global_ca_crt_base(char **args, int section_type, struct proxy *curpx,
9041 struct proxy *defpx, const char *file, int line,
9042 char **err)
9043{
9044 char **target;
9045
Willy Tarreauef934602016-12-22 23:12:01 +01009046 target = (args[0][1] == 'a') ? &global_ssl.ca_base : &global_ssl.crt_base;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009047
9048 if (too_many_args(1, args, err, NULL))
9049 return -1;
9050
9051 if (*target) {
9052 memprintf(err, "'%s' already specified.", args[0]);
9053 return -1;
9054 }
9055
9056 if (*(args[1]) == 0) {
9057 memprintf(err, "global statement '%s' expects a directory path as an argument.", args[0]);
9058 return -1;
9059 }
9060 *target = strdup(args[1]);
9061 return 0;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009062}
9063
9064/* parse the "ssl-mode-async" keyword in global section.
9065 * Returns <0 on alert, >0 on warning, 0 on success.
9066 */
9067static int ssl_parse_global_ssl_async(char **args, int section_type, struct proxy *curpx,
9068 struct proxy *defpx, const char *file, int line,
9069 char **err)
9070{
Willy Tarreau5db847a2019-05-09 14:13:35 +02009071#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) && !defined(OPENSSL_NO_ASYNC)
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009072 global_ssl.async = 1;
Emeric Brunece0c332017-12-06 13:51:49 +01009073 global.ssl_used_async_engines = nb_engines;
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009074 return 0;
9075#else
9076 memprintf(err, "'%s': openssl library does not support async mode", args[0]);
9077 return -1;
9078#endif
9079}
9080
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009081#ifndef OPENSSL_NO_ENGINE
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009082static int ssl_check_async_engine_count(void) {
9083 int err_code = 0;
9084
Emeric Brun3854e012017-05-17 20:42:48 +02009085 if (global_ssl.async && (openssl_engines_initialized > 32)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01009086 ha_alert("ssl-mode-async only supports a maximum of 32 engines.\n");
Grant Zhangfa6c7ee2017-01-14 01:42:15 +00009087 err_code = ERR_ABORT;
9088 }
9089 return err_code;
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +01009090}
9091
Grant Zhang872f9c22017-01-21 01:10:18 +00009092/* parse the "ssl-engine" keyword in global section.
9093 * Returns <0 on alert, >0 on warning, 0 on success.
9094 */
9095static int ssl_parse_global_ssl_engine(char **args, int section_type, struct proxy *curpx,
9096 struct proxy *defpx, const char *file, int line,
9097 char **err)
9098{
9099 char *algo;
9100 int ret = -1;
9101
9102 if (*(args[1]) == 0) {
9103 memprintf(err, "global statement '%s' expects a valid engine name as an argument.", args[0]);
9104 return ret;
9105 }
9106
9107 if (*(args[2]) == 0) {
9108 /* if no list of algorithms is given, it defaults to ALL */
9109 algo = strdup("ALL");
9110 goto add_engine;
9111 }
9112
9113 /* otherwise the expected format is ssl-engine <engine_name> algo <list of algo> */
9114 if (strcmp(args[2], "algo") != 0) {
9115 memprintf(err, "global statement '%s' expects to have algo keyword.", args[0]);
9116 return ret;
9117 }
9118
9119 if (*(args[3]) == 0) {
9120 memprintf(err, "global statement '%s' expects algorithm names as an argument.", args[0]);
9121 return ret;
9122 }
9123 algo = strdup(args[3]);
9124
9125add_engine:
9126 if (ssl_init_single_engine(args[1], algo)==0) {
9127 openssl_engines_initialized++;
9128 ret = 0;
9129 }
9130 free(algo);
9131 return ret;
9132}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +02009133#endif
Grant Zhang872f9c22017-01-21 01:10:18 +00009134
Willy Tarreauf22e9682016-12-21 23:23:19 +01009135/* parse the "ssl-default-bind-ciphers" / "ssl-default-server-ciphers" keywords
9136 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9137 */
9138static int ssl_parse_global_ciphers(char **args, int section_type, struct proxy *curpx,
9139 struct proxy *defpx, const char *file, int line,
9140 char **err)
9141{
9142 char **target;
9143
Willy Tarreauef934602016-12-22 23:12:01 +01009144 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphers : &global_ssl.connect_default_ciphers;
Willy Tarreauf22e9682016-12-21 23:23:19 +01009145
9146 if (too_many_args(1, args, err, NULL))
9147 return -1;
9148
9149 if (*(args[1]) == 0) {
9150 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9151 return -1;
9152 }
9153
9154 free(*target);
9155 *target = strdup(args[1]);
9156 return 0;
9157}
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009158
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009159#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +02009160/* parse the "ssl-default-bind-ciphersuites" / "ssl-default-server-ciphersuites" keywords
9161 * in global section. Returns <0 on alert, >0 on warning, 0 on success.
9162 */
9163static int ssl_parse_global_ciphersuites(char **args, int section_type, struct proxy *curpx,
9164 struct proxy *defpx, const char *file, int line,
9165 char **err)
9166{
9167 char **target;
9168
9169 target = (args[0][12] == 'b') ? &global_ssl.listen_default_ciphersuites : &global_ssl.connect_default_ciphersuites;
9170
9171 if (too_many_args(1, args, err, NULL))
9172 return -1;
9173
9174 if (*(args[1]) == 0) {
9175 memprintf(err, "global statement '%s' expects a cipher suite as an argument.", args[0]);
9176 return -1;
9177 }
9178
9179 free(*target);
9180 *target = strdup(args[1]);
9181 return 0;
9182}
9183#endif
Willy Tarreauf22e9682016-12-21 23:23:19 +01009184
Willy Tarreau9ceda382016-12-21 23:13:03 +01009185/* parse various global tune.ssl settings consisting in positive integers.
9186 * Returns <0 on alert, >0 on warning, 0 on success.
9187 */
9188static int ssl_parse_global_int(char **args, int section_type, struct proxy *curpx,
9189 struct proxy *defpx, const char *file, int line,
9190 char **err)
9191{
9192 int *target;
9193
9194 if (strcmp(args[0], "tune.ssl.cachesize") == 0)
9195 target = &global.tune.sslcachesize;
9196 else if (strcmp(args[0], "tune.ssl.maxrecord") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009197 target = (int *)&global_ssl.max_record;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009198 else if (strcmp(args[0], "tune.ssl.ssl-ctx-cache-size") == 0)
Willy Tarreauef934602016-12-22 23:12:01 +01009199 target = &global_ssl.ctx_cache;
Willy Tarreau0bea58d2016-12-21 23:17:25 +01009200 else if (strcmp(args[0], "maxsslconn") == 0)
9201 target = &global.maxsslconn;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009202 else if (strcmp(args[0], "tune.ssl.capture-cipherlist-size") == 0)
9203 target = &global_ssl.capture_cipherlist;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009204 else {
9205 memprintf(err, "'%s' keyword not unhandled (please report this bug).", args[0]);
9206 return -1;
9207 }
9208
9209 if (too_many_args(1, args, err, NULL))
9210 return -1;
9211
9212 if (*(args[1]) == 0) {
9213 memprintf(err, "'%s' expects an integer argument.", args[0]);
9214 return -1;
9215 }
9216
9217 *target = atoi(args[1]);
9218 if (*target < 0) {
9219 memprintf(err, "'%s' expects a positive numeric value.", args[0]);
9220 return -1;
9221 }
9222 return 0;
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009223}
9224
9225static int ssl_parse_global_capture_cipherlist(char **args, int section_type, struct proxy *curpx,
9226 struct proxy *defpx, const char *file, int line,
9227 char **err)
9228{
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009229 int ret;
9230
9231 ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
9232 if (ret != 0)
9233 return ret;
9234
Willy Tarreaubafbe012017-11-24 17:34:44 +01009235 if (pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009236 memprintf(err, "'%s' is already configured.", args[0]);
9237 return -1;
9238 }
9239
Willy Tarreaubafbe012017-11-24 17:34:44 +01009240 pool_head_ssl_capture = create_pool("ssl-capture", sizeof(struct ssl_capture) + global_ssl.capture_cipherlist, MEM_F_SHARED);
9241 if (!pool_head_ssl_capture) {
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009242 memprintf(err, "Out of memory error.");
9243 return -1;
9244 }
9245 return 0;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009246}
9247
9248/* parse "ssl.force-private-cache".
9249 * Returns <0 on alert, >0 on warning, 0 on success.
9250 */
9251static int ssl_parse_global_private_cache(char **args, int section_type, struct proxy *curpx,
9252 struct proxy *defpx, const char *file, int line,
9253 char **err)
9254{
9255 if (too_many_args(0, args, err, NULL))
9256 return -1;
9257
Willy Tarreauef934602016-12-22 23:12:01 +01009258 global_ssl.private_cache = 1;
Willy Tarreau9ceda382016-12-21 23:13:03 +01009259 return 0;
9260}
9261
9262/* parse "ssl.lifetime".
9263 * Returns <0 on alert, >0 on warning, 0 on success.
9264 */
9265static int ssl_parse_global_lifetime(char **args, int section_type, struct proxy *curpx,
9266 struct proxy *defpx, const char *file, int line,
9267 char **err)
9268{
9269 const char *res;
9270
9271 if (too_many_args(1, args, err, NULL))
9272 return -1;
9273
9274 if (*(args[1]) == 0) {
9275 memprintf(err, "'%s' expects ssl sessions <lifetime> in seconds as argument.", args[0]);
9276 return -1;
9277 }
9278
Willy Tarreauef934602016-12-22 23:12:01 +01009279 res = parse_time_err(args[1], &global_ssl.life_time, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02009280 if (res == PARSE_TIME_OVER) {
9281 memprintf(err, "timer overflow in argument '%s' to <%s> (maximum value is 2147483647 s or ~68 years).",
9282 args[1], args[0]);
9283 return -1;
9284 }
9285 else if (res == PARSE_TIME_UNDER) {
9286 memprintf(err, "timer underflow in argument '%s' to <%s> (minimum non-null value is 1 s).",
9287 args[1], args[0]);
9288 return -1;
9289 }
9290 else if (res) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009291 memprintf(err, "unexpected character '%c' in argument to <%s>.", *res, args[0]);
9292 return -1;
9293 }
9294 return 0;
9295}
9296
9297#ifndef OPENSSL_NO_DH
Willy Tarreau14e36a12016-12-21 23:28:13 +01009298/* parse "ssl-dh-param-file".
9299 * Returns <0 on alert, >0 on warning, 0 on success.
9300 */
9301static int ssl_parse_global_dh_param_file(char **args, int section_type, struct proxy *curpx,
9302 struct proxy *defpx, const char *file, int line,
9303 char **err)
9304{
9305 if (too_many_args(1, args, err, NULL))
9306 return -1;
9307
9308 if (*(args[1]) == 0) {
9309 memprintf(err, "'%s' expects a file path as an argument.", args[0]);
9310 return -1;
9311 }
9312
9313 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
9314 memprintf(err, "'%s': unable to load DH parameters from file <%s>.", args[0], args[1]);
9315 return -1;
9316 }
9317 return 0;
9318}
9319
Willy Tarreau9ceda382016-12-21 23:13:03 +01009320/* parse "ssl.default-dh-param".
9321 * Returns <0 on alert, >0 on warning, 0 on success.
9322 */
9323static int ssl_parse_global_default_dh(char **args, int section_type, struct proxy *curpx,
9324 struct proxy *defpx, const char *file, int line,
9325 char **err)
9326{
9327 if (too_many_args(1, args, err, NULL))
9328 return -1;
9329
9330 if (*(args[1]) == 0) {
9331 memprintf(err, "'%s' expects an integer argument.", args[0]);
9332 return -1;
9333 }
9334
Willy Tarreauef934602016-12-22 23:12:01 +01009335 global_ssl.default_dh_param = atoi(args[1]);
9336 if (global_ssl.default_dh_param < 1024) {
Willy Tarreau9ceda382016-12-21 23:13:03 +01009337 memprintf(err, "'%s' expects a value >= 1024.", args[0]);
9338 return -1;
9339 }
9340 return 0;
9341}
9342#endif
9343
9344
William Lallemand32af2032016-10-29 18:09:35 +02009345/* This function is used with TLS ticket keys management. It permits to browse
9346 * each reference. The variable <getnext> must contain the current node,
9347 * <end> point to the root node.
9348 */
9349#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9350static inline
9351struct tls_keys_ref *tlskeys_list_get_next(struct tls_keys_ref *getnext, struct list *end)
9352{
9353 struct tls_keys_ref *ref = getnext;
9354
9355 while (1) {
9356
9357 /* Get next list entry. */
9358 ref = LIST_NEXT(&ref->list, struct tls_keys_ref *, list);
9359
9360 /* If the entry is the last of the list, return NULL. */
9361 if (&ref->list == end)
9362 return NULL;
9363
9364 return ref;
9365 }
9366}
9367
9368static inline
9369struct tls_keys_ref *tlskeys_ref_lookup_ref(const char *reference)
9370{
9371 int id;
9372 char *error;
9373
9374 /* If the reference starts by a '#', this is numeric id. */
9375 if (reference[0] == '#') {
9376 /* Try to convert the numeric id. If the conversion fails, the lookup fails. */
9377 id = strtol(reference + 1, &error, 10);
9378 if (*error != '\0')
9379 return NULL;
9380
9381 /* Perform the unique id lookup. */
9382 return tlskeys_ref_lookupid(id);
9383 }
9384
9385 /* Perform the string lookup. */
9386 return tlskeys_ref_lookup(reference);
9387}
9388#endif
9389
9390
9391#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9392
9393static int cli_io_handler_tlskeys_files(struct appctx *appctx);
9394
9395static inline int cli_io_handler_tlskeys_entries(struct appctx *appctx) {
9396 return cli_io_handler_tlskeys_files(appctx);
9397}
9398
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009399/* dumps all tls keys. Relies on cli.i0 (non-null = only list file names), cli.i1
9400 * (next index to be dumped), and cli.p0 (next key reference).
9401 */
William Lallemand32af2032016-10-29 18:09:35 +02009402static int cli_io_handler_tlskeys_files(struct appctx *appctx) {
9403
9404 struct stream_interface *si = appctx->owner;
9405
9406 switch (appctx->st2) {
9407 case STAT_ST_INIT:
9408 /* Display the column headers. If the message cannot be sent,
Joseph Herlant017b3da2018-11-15 09:07:59 -08009409 * quit the function with returning 0. The function is called
William Lallemand32af2032016-10-29 18:09:35 +02009410 * later and restart at the state "STAT_ST_INIT".
9411 */
9412 chunk_reset(&trash);
9413
9414 if (appctx->io_handler == cli_io_handler_tlskeys_entries)
9415 chunk_appendf(&trash, "# id secret\n");
9416 else
9417 chunk_appendf(&trash, "# id (file)\n");
9418
Willy Tarreau06d80a92017-10-19 14:32:15 +02009419 if (ci_putchk(si_ic(si), &trash) == -1) {
Willy Tarreaudb398432018-11-15 11:08:52 +01009420 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009421 return 0;
9422 }
9423
William Lallemand32af2032016-10-29 18:09:35 +02009424 /* Now, we start the browsing of the references lists.
9425 * Note that the following call to LIST_ELEM return bad pointer. The only
9426 * available field of this pointer is <list>. It is used with the function
9427 * tlskeys_list_get_next() for retruning the first available entry
9428 */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009429 if (appctx->ctx.cli.p0 == NULL) {
9430 appctx->ctx.cli.p0 = LIST_ELEM(&tlskeys_reference, struct tls_keys_ref *, list);
9431 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009432 }
9433
9434 appctx->st2 = STAT_ST_LIST;
9435 /* fall through */
9436
9437 case STAT_ST_LIST:
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009438 while (appctx->ctx.cli.p0) {
9439 struct tls_keys_ref *ref = appctx->ctx.cli.p0;
William Lallemand32af2032016-10-29 18:09:35 +02009440
9441 chunk_reset(&trash);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009442 if (appctx->io_handler == cli_io_handler_tlskeys_entries && appctx->ctx.cli.i1 == 0)
William Lallemand32af2032016-10-29 18:09:35 +02009443 chunk_appendf(&trash, "# ");
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009444
9445 if (appctx->ctx.cli.i1 == 0)
9446 chunk_appendf(&trash, "%d (%s)\n", ref->unique_id, ref->filename);
9447
William Lallemand32af2032016-10-29 18:09:35 +02009448 if (appctx->io_handler == cli_io_handler_tlskeys_entries) {
Christopher Faulet16f45c82018-02-16 11:23:49 +01009449 int head;
9450
9451 HA_RWLOCK_RDLOCK(TLSKEYS_REF_LOCK, &ref->lock);
9452 head = ref->tls_ticket_enc_index;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009453 while (appctx->ctx.cli.i1 < TLS_TICKETS_NO) {
Willy Tarreau83061a82018-07-13 11:56:34 +02009454 struct buffer *t2 = get_trash_chunk();
William Lallemand32af2032016-10-29 18:09:35 +02009455
9456 chunk_reset(t2);
9457 /* should never fail here because we dump only a key in the t2 buffer */
Emeric Brun9e754772019-01-10 17:51:55 +01009458 if (ref->key_size_bits == 128) {
9459 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9460 sizeof(struct tls_sess_key_128),
9461 t2->area, t2->size);
9462 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9463 t2->area);
9464 }
9465 else if (ref->key_size_bits == 256) {
9466 t2->data = a2base64((char *)(ref->tlskeys + (head + 2 + appctx->ctx.cli.i1) % TLS_TICKETS_NO),
9467 sizeof(struct tls_sess_key_256),
9468 t2->area, t2->size);
9469 chunk_appendf(&trash, "%d.%d %s\n", ref->unique_id, appctx->ctx.cli.i1,
9470 t2->area);
9471 }
9472 else {
9473 /* This case should never happen */
9474 chunk_appendf(&trash, "%d.%d <unknown>\n", ref->unique_id, appctx->ctx.cli.i1);
9475 }
William Lallemand32af2032016-10-29 18:09:35 +02009476
Willy Tarreau06d80a92017-10-19 14:32:15 +02009477 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009478 /* let's try again later from this stream. We add ourselves into
9479 * this stream's users so that it can remove us upon termination.
9480 */
Christopher Faulet16f45c82018-02-16 11:23:49 +01009481 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreaudb398432018-11-15 11:08:52 +01009482 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009483 return 0;
9484 }
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009485 appctx->ctx.cli.i1++;
William Lallemand32af2032016-10-29 18:09:35 +02009486 }
Christopher Faulet16f45c82018-02-16 11:23:49 +01009487 HA_RWLOCK_RDUNLOCK(TLSKEYS_REF_LOCK, &ref->lock);
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009488 appctx->ctx.cli.i1 = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009489 }
Willy Tarreau06d80a92017-10-19 14:32:15 +02009490 if (ci_putchk(si_ic(si), &trash) == -1) {
William Lallemand32af2032016-10-29 18:09:35 +02009491 /* let's try again later from this stream. We add ourselves into
9492 * this stream's users so that it can remove us upon termination.
9493 */
Willy Tarreaudb398432018-11-15 11:08:52 +01009494 si_rx_room_blk(si);
William Lallemand32af2032016-10-29 18:09:35 +02009495 return 0;
9496 }
9497
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009498 if (appctx->ctx.cli.i0 == 0) /* don't display everything if not necessary */
William Lallemand32af2032016-10-29 18:09:35 +02009499 break;
9500
9501 /* get next list entry and check the end of the list */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009502 appctx->ctx.cli.p0 = tlskeys_list_get_next(appctx->ctx.cli.p0, &tlskeys_reference);
William Lallemand32af2032016-10-29 18:09:35 +02009503 }
9504
9505 appctx->st2 = STAT_ST_FIN;
9506 /* fall through */
9507
9508 default:
9509 appctx->st2 = STAT_ST_FIN;
9510 return 1;
9511 }
9512 return 0;
9513}
9514
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009515/* sets cli.i0 to non-zero if only file lists should be dumped */
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009516static int cli_parse_show_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009517{
William Lallemand32af2032016-10-29 18:09:35 +02009518 /* no parameter, shows only file list */
9519 if (!*args[2]) {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009520 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009521 appctx->io_handler = cli_io_handler_tlskeys_files;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009522 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009523 }
9524
9525 if (args[2][0] == '*') {
9526 /* list every TLS ticket keys */
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009527 appctx->ctx.cli.i0 = 1;
William Lallemand32af2032016-10-29 18:09:35 +02009528 } else {
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009529 appctx->ctx.cli.p0 = tlskeys_ref_lookup_ref(args[2]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009530 if (!appctx->ctx.cli.p0)
9531 return cli_err(appctx, "'show tls-keys' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009532 }
William Lallemand32af2032016-10-29 18:09:35 +02009533 appctx->io_handler = cli_io_handler_tlskeys_entries;
Willy Tarreau3067bfa2016-12-05 14:50:15 +01009534 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009535}
9536
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009537static int cli_parse_set_tlskeys(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009538{
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009539 struct tls_keys_ref *ref;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009540 int ret;
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009541
William Lallemand32af2032016-10-29 18:09:35 +02009542 /* Expect two parameters: the filename and the new new TLS key in encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009543 if (!*args[3] || !*args[4])
9544 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 +02009545
Willy Tarreauf5f26e82016-12-16 18:47:27 +01009546 ref = tlskeys_ref_lookup_ref(args[3]);
Willy Tarreau9d008692019-08-09 11:21:01 +02009547 if (!ref)
9548 return cli_err(appctx, "'set ssl tls-key' unable to locate referenced filename\n");
William Lallemand32af2032016-10-29 18:09:35 +02009549
Willy Tarreau1c913e42018-08-22 05:26:57 +02009550 ret = base64dec(args[4], strlen(args[4]), trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009551 if (ret < 0)
9552 return cli_err(appctx, "'set ssl tls-key' received invalid base64 encoded TLS key.\n");
Emeric Brun9e754772019-01-10 17:51:55 +01009553
Willy Tarreau1c913e42018-08-22 05:26:57 +02009554 trash.data = ret;
Willy Tarreau9d008692019-08-09 11:21:01 +02009555 if (ssl_sock_update_tlskey_ref(ref, &trash) < 0)
9556 return cli_err(appctx, "'set ssl tls-key' received a key of wrong size.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009557
Willy Tarreau9d008692019-08-09 11:21:01 +02009558 return cli_msg(appctx, LOG_INFO, "TLS ticket key updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009559}
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009560#endif
William Lallemand32af2032016-10-29 18:09:35 +02009561
William Lallemand150bfa82019-09-19 17:12:49 +02009562static int cli_parse_set_cert(char **args, char *payload, struct appctx *appctx, void *private)
9563{
9564 struct ckch_store *ckchs = NULL;
9565 struct cert_key_and_chain *ckch;
9566 struct list tmp_ckchi_list;
9567 BIO *mem;
9568 char *err = NULL;
William Lallemand963b2e72019-10-14 11:38:36 +02009569 int i;
William Lallemand150bfa82019-09-19 17:12:49 +02009570 int found = 0;
9571 int bundle = -1;
9572 int ret = 0;
9573
9574 if (!*args[3] || !payload)
9575 return cli_err(appctx, "'set ssl cert expects a filename and a certificat as a payload\n");
9576
9577 /* The operations on the CKCH architecture are locked so we can
9578 * manipulate ckch_store and ckch_inst */
9579 if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
9580 return cli_err(appctx, "Can't update the certificate!\nOperations on certificates are currently locked!\n");
9581
9582 LIST_INIT(&tmp_ckchi_list);
9583
9584 mem = BIO_new_mem_buf(payload, -1);
9585 if (!mem) {
9586 memprintf(&err, "%sCan't allocate memory\n", err ? err : "");
9587 ret = 1;
9588 goto end;
9589 }
9590
9591 /* do 2 iterations, first one with a non-bundle entry, second one with a bundle entry */
9592 for (i = 0; i < 2; i++) {
9593
9594 if ((ckchs = ckchs_lookup(args[3])) != NULL) {
9595 struct ckch_inst *ckchi, *ckchis;
9596
9597 /* only the bundle name is in the tree and you should never update a bundle name, only a filename */
9598 if (bundle < 0 && ckchs->multi) {
9599 memprintf(&err, "%s%s is a multi-cert bundle. Try updating %s.{dsa,rsa,ecdsa}\n",
9600 err ? err : "", args[3], args[3]);
9601 ret = 1;
9602 goto end;
9603 }
9604
9605 if (bundle < 0)
9606 ckch = ckchs->ckch;
9607 else
9608 ckch = &ckchs->ckch[bundle];
9609
9610 if (ckchs->filters) {
9611 memprintf(&err, "%sCertificates used in crt-list with filters are not supported!\n",
9612 err ? err : "");
9613 ret = 1;
9614 goto end;
9615 }
9616
9617 found = 1;
9618
9619 if (ssl_sock_load_crt_file_into_ckch(args[3], mem, ckch, &err) != 0) {
9620 ret = 1;
9621 goto end;
9622 }
9623
9624 /* walk through ckch_inst and creates new ckch_inst using the updated ckch */
9625 list_for_each_entry(ckchi, &ckchs->ckch_inst, by_ckchs) {
9626 struct ckch_inst *new_inst;
9627
9628 if (ckchs->multi)
9629 new_inst = ckch_inst_new_load_multi_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &err);
9630 else
9631 new_inst = ckch_inst_new_load_store(args[3], ckchs, ckchi->bind_conf, ckchi->ssl_conf, NULL, 0, &err);
9632
9633 if (!new_inst) {
9634 ret = 1;
9635 goto end;
9636 }
9637
9638 /* link temporary the new ckch_inst */
9639 LIST_ADDQ(&tmp_ckchi_list, &new_inst->by_ckchs);
9640 }
9641
9642 /* once every allocation is done, delete the old sni_ctx & the old ckch_insts */
9643 list_for_each_entry_safe(ckchi, ckchis, &ckchs->ckch_inst, by_ckchs) {
9644 struct sni_ctx *sc0, *sc0s;
9645
9646 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9647 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9648 ebmb_delete(&sc0->name);
9649 LIST_DEL(&sc0->by_ckch_inst);
9650 free(sc0);
9651 }
9652 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9653 LIST_DEL(&ckchi->by_ckchs);
9654 free(ckchi);
9655 ckchi = NULL;
9656 }
9657 /* insert every new ckch instance in the actual list and insert the sni_ctx in the trees */
9658 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9659 LIST_DEL(&ckchi->by_ckchs);
9660 LIST_ADD(&ckchs->ckch_inst, &ckchi->by_ckchs);
9661 HA_RWLOCK_WRLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9662 ssl_sock_load_cert_sni(ckchi, ckchi->bind_conf);
9663 HA_RWLOCK_WRUNLOCK(CKCH_LOCK, &ckchi->bind_conf->sni_lock);
9664 }
9665 }
William Lallemand963b2e72019-10-14 11:38:36 +02009666#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
9667 {
9668 char *end = NULL;
9669 int j;
William Lallemand150bfa82019-09-19 17:12:49 +02009670
William Lallemand963b2e72019-10-14 11:38:36 +02009671 /* check if it was also used as a bundle by removing the
9672 * .dsa/.rsa/.ecdsa at the end of the filename */
9673 if (bundle >= 0)
William Lallemand150bfa82019-09-19 17:12:49 +02009674 break;
William Lallemand963b2e72019-10-14 11:38:36 +02009675 end = strrchr(args[3], '.');
9676 for (j = 0; *end && j < SSL_SOCK_NUM_KEYTYPES; j++) {
9677 if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
9678 bundle = j; /* keep the type of certificate so we insert it at the right place */
9679 *end = '\0'; /* it's a bundle let's end the string*/
9680 break;
9681 }
William Lallemand150bfa82019-09-19 17:12:49 +02009682 }
9683 }
William Lallemand963b2e72019-10-14 11:38:36 +02009684#else
9685 /* bundles are not supported here, so we don't need to lookup again */
9686 break;
9687#endif
William Lallemand150bfa82019-09-19 17:12:49 +02009688 }
9689
9690 if (!found) {
9691 ret = 1;
9692 memprintf(&err, "%sCan't replace a certificate name which is not referenced by the configuration!\n",
9693 err ? err : "");
9694 }
9695
9696end:
9697
9698 HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
9699
9700 BIO_free(mem);
9701
9702 if (ret != 0) {
9703 struct ckch_inst *ckchi, *ckchis;
9704 /* if the allocation failed, we need to free everything from the temporary list */
9705 list_for_each_entry_safe(ckchi, ckchis, &tmp_ckchi_list, by_ckchs) {
9706 struct sni_ctx *sc0, *sc0s;
9707
9708 list_for_each_entry_safe(sc0, sc0s, &ckchi->sni_ctx, by_ckch_inst) {
9709 if (sc0->order == 0) /* we only free if it's the first inserted */
9710 SSL_CTX_free(sc0->ctx);
9711 LIST_DEL(&sc0->by_ckch_inst);
9712 free(sc0);
9713 }
9714 LIST_DEL(&ckchi->by_ckchs);
9715 free(ckchi);
9716 }
9717 return cli_dynerr(appctx, memprintf(&err, "%sCan't update the certificate!\n", err ? err : ""));
9718 } else {
9719 return cli_dynmsg(appctx, LOG_INFO, memprintf(&err, "Certificate updated!"));
9720 }
9721}
9722
Aurélien Nephtaliabbf6072018-04-18 13:26:46 +02009723static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx *appctx, void *private)
William Lallemand32af2032016-10-29 18:09:35 +02009724{
9725#if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
9726 char *err = NULL;
Willy Tarreau1c913e42018-08-22 05:26:57 +02009727 int i, j, ret;
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009728
9729 if (!payload)
9730 payload = args[3];
William Lallemand32af2032016-10-29 18:09:35 +02009731
9732 /* Expect one parameter: the new response in base64 encoding */
Willy Tarreau9d008692019-08-09 11:21:01 +02009733 if (!*payload)
9734 return cli_err(appctx, "'set ssl ocsp-response' expects response in base64 encoding.\n");
Aurélien Nephtali1e0867c2018-04-18 14:04:58 +02009735
9736 /* remove \r and \n from the payload */
9737 for (i = 0, j = 0; payload[i]; i++) {
9738 if (payload[i] == '\r' || payload[i] == '\n')
9739 continue;
9740 payload[j++] = payload[i];
9741 }
9742 payload[j] = 0;
William Lallemand32af2032016-10-29 18:09:35 +02009743
Willy Tarreau1c913e42018-08-22 05:26:57 +02009744 ret = base64dec(payload, j, trash.area, trash.size);
Willy Tarreau9d008692019-08-09 11:21:01 +02009745 if (ret < 0)
9746 return cli_err(appctx, "'set ssl ocsp-response' received invalid base64 encoded response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009747
Willy Tarreau1c913e42018-08-22 05:26:57 +02009748 trash.data = ret;
William Lallemand32af2032016-10-29 18:09:35 +02009749 if (ssl_sock_update_ocsp_response(&trash, &err)) {
Willy Tarreau9d008692019-08-09 11:21:01 +02009750 if (err)
9751 return cli_dynerr(appctx, memprintf(&err, "%s.\n", err));
9752 else
9753 return cli_err(appctx, "Failed to update OCSP response.\n");
William Lallemand32af2032016-10-29 18:09:35 +02009754 }
Willy Tarreau9d008692019-08-09 11:21:01 +02009755
9756 return cli_msg(appctx, LOG_INFO, "OCSP Response updated!\n");
William Lallemand32af2032016-10-29 18:09:35 +02009757#else
Willy Tarreau9d008692019-08-09 11:21:01 +02009758 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 +02009759#endif
9760
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009761}
9762
Willy Tarreau86a394e2019-05-09 14:15:32 +02009763#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009764static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp)
9765{
9766 switch (arg->type) {
9767 case ARGT_STR:
9768 smp->data.type = SMP_T_STR;
9769 smp->data.u.str = arg->data.str;
9770 return 1;
9771 case ARGT_VAR:
9772 if (!vars_get_by_desc(&arg->data.var, smp))
9773 return 0;
9774 if (!sample_casts[smp->data.type][SMP_T_STR])
9775 return 0;
9776 if (!sample_casts[smp->data.type][SMP_T_STR](smp))
9777 return 0;
9778 return 1;
9779 default:
9780 return 0;
9781 }
9782}
9783
9784static int check_aes_gcm(struct arg *args, struct sample_conv *conv,
9785 const char *file, int line, char **err)
9786{
9787 switch(args[0].data.sint) {
9788 case 128:
9789 case 192:
9790 case 256:
9791 break;
9792 default:
9793 memprintf(err, "key size must be 128, 192 or 256 (bits).");
9794 return 0;
9795 }
9796 /* Try to decode a variable. */
9797 vars_check_arg(&args[1], NULL);
9798 vars_check_arg(&args[2], NULL);
9799 vars_check_arg(&args[3], NULL);
9800 return 1;
9801}
9802
9803/* Arguements: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
9804static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private)
9805{
9806 struct sample nonce, key, aead_tag;
9807 struct buffer *smp_trash, *smp_trash_alloc;
9808 EVP_CIPHER_CTX *ctx;
9809 int dec_size, ret;
9810
9811 smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt);
9812 if (!sample_conv_var2smp_str(&arg_p[1], &nonce))
9813 return 0;
9814
9815 smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt);
9816 if (!sample_conv_var2smp_str(&arg_p[2], &key))
9817 return 0;
9818
9819 smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt);
9820 if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag))
9821 return 0;
9822
9823 smp_trash = get_trash_chunk();
9824 smp_trash_alloc = alloc_trash_chunk();
9825 if (!smp_trash_alloc)
9826 return 0;
9827
9828 ctx = EVP_CIPHER_CTX_new();
9829
9830 if (!ctx)
9831 goto err;
9832
9833 dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size);
9834 if (dec_size < 0)
9835 goto err;
9836 smp_trash->data = dec_size;
9837
9838 /* Set cipher type and mode */
9839 switch(arg_p[0].data.sint) {
9840 case 128:
9841 EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
9842 break;
9843 case 192:
9844 EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL);
9845 break;
9846 case 256:
9847 EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
9848 break;
9849 }
9850
9851 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL);
9852
9853 /* Initialise IV */
9854 if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area))
9855 goto err;
9856
9857 dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size);
9858 if (dec_size < 0)
9859 goto err;
9860 smp_trash->data = dec_size;
9861
9862 /* Initialise key */
9863 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL))
9864 goto err;
9865
9866 if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
9867 (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data))
9868 goto err;
9869
9870 dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size);
9871 if (dec_size < 0)
9872 goto err;
9873 smp_trash_alloc->data = dec_size;
9874 dec_size = smp_trash->data;
9875
9876 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area);
9877 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data);
9878
9879 if (ret <= 0)
9880 goto err;
9881
9882 smp->data.u.str.data = dec_size + smp_trash->data;
9883 smp->data.u.str.area = smp_trash->area;
9884 smp->data.type = SMP_T_BIN;
9885 smp->flags &= ~SMP_F_CONST;
9886 free_trash_chunk(smp_trash_alloc);
9887 return 1;
9888
9889err:
9890 free_trash_chunk(smp_trash_alloc);
9891 return 0;
William Lallemand32af2032016-10-29 18:09:35 +02009892}
Nenad Merdanovicc31499d2019-03-23 11:00:32 +01009893# endif
William Lallemand32af2032016-10-29 18:09:35 +02009894
9895/* register cli keywords */
9896static struct cli_kw_list cli_kws = {{ },{
9897#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
9898 { { "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 +02009899 { { "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 +02009900#endif
Emmanuel Hocdetfdec7892017-01-13 17:48:18 +01009901 { { "set", "ssl", "ocsp-response", NULL }, NULL, cli_parse_set_ocspresponse, NULL },
William Lallemand150bfa82019-09-19 17:12:49 +02009902 { { "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 +02009903 { { NULL }, NULL, NULL, NULL }
9904}};
9905
Willy Tarreau0108d902018-11-25 19:14:37 +01009906INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
William Lallemand32af2032016-10-29 18:09:35 +02009907
Willy Tarreau7875d092012-09-10 08:20:03 +02009908/* Note: must not be declared <const> as its list will be overwritten.
9909 * Please take care of keeping this list alphabetically sorted.
9910 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009911static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
Emeric Brun645ae792014-04-30 14:21:06 +02009912 { "ssl_bc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5SRV },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009913 { "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 +01009914#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Jérôme Magnine064a802018-12-03 22:21:04 +01009915 { "ssl_bc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009916#endif
Emeric Brun645ae792014-04-30 14:21:06 +02009917 { "ssl_bc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Olivier Houchard6b77f492018-11-22 18:18:29 +01009918#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
9919 { "ssl_bc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
9920#endif
Emeric Brun74f7ffa2018-02-19 16:14:12 +01009921 { "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 +02009922 { "ssl_bc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5SRV },
Emeric Brunb73a9b02014-04-30 18:49:19 +02009923 { "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 +02009924 { "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 +02009925#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brun645ae792014-04-30 14:21:06 +02009926 { "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 -04009927#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009928#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009929 { "ssl_bc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9930 { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
Patrick Hemmere0275472018-04-28 19:15:51 -04009931 { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV },
9932#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009933 { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9934 { "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 +01009935 { "ssl_c_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009936 { "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009937 { "ssl_c_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9938 { "ssl_c_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9939 { "ssl_c_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9940 { "ssl_c_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9941 { "ssl_c_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9942 { "ssl_c_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9943 { "ssl_c_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9944 { "ssl_c_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009945 { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009946 { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
9947 { "ssl_c_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Emeric Brun43e79582014-10-29 19:03:26 +01009948 { "ssl_f_der", smp_fetch_ssl_x_der, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brunba841a12014-04-30 17:05:08 +02009949 { "ssl_f_i_dn", smp_fetch_ssl_x_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9950 { "ssl_f_key_alg", smp_fetch_ssl_x_key_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9951 { "ssl_f_notafter", smp_fetch_ssl_x_notafter, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9952 { "ssl_f_notbefore", smp_fetch_ssl_x_notbefore, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9953 { "ssl_f_sig_alg", smp_fetch_ssl_x_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9954 { "ssl_f_s_dn", smp_fetch_ssl_x_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
9955 { "ssl_f_serial", smp_fetch_ssl_x_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Emeric Brun55f4fa82014-04-30 17:11:25 +02009956 { "ssl_f_sha1", smp_fetch_ssl_x_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009957 { "ssl_f_version", smp_fetch_ssl_x_version, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009958 { "ssl_fc", smp_fetch_ssl_fc, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009959 { "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 +01009960 { "ssl_fc_cipher", smp_fetch_ssl_fc_cipher, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau80aca902013-01-07 15:42:20 +01009961 { "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 +02009962 { "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 +01009963 { "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 +02009964 { "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 +01009965#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009966 { "ssl_fc_npn", smp_fetch_ssl_fc_npn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreaua33c6542012-10-15 13:19:06 +02009967#endif
Dirkjan Bussink48f1c4e2014-02-13 12:29:42 +01009968#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009969 { "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreauab861d32013-04-02 02:30:41 +02009970#endif
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009971 { "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Willy Tarreau9a1ab082019-05-09 13:26:41 +02009972#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Emeric Brunb73a9b02014-04-30 18:49:19 +02009973 { "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 -04009974#endif
Thierry FOURNIER07ee64e2015-07-06 23:43:03 +02009975 { "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 +02009976#if HA_OPENSSL_VERSION_NUMBER > 0x0090800fL
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009977 { "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 -04009978#endif
Emmanuel Hocdet839af572019-05-14 16:27:35 +02009979#if HA_OPENSSL_VERSION_NUMBER >= 0x10100000L
Patrick Hemmer65674662019-06-04 08:13:03 -04009980 { "ssl_fc_client_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9981 { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
Patrick Hemmere0275472018-04-28 19:15:51 -04009982 { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9983#endif
Patrick Hemmer41966772018-04-28 19:15:48 -04009984#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01009985 { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
Patrick Hemmer41966772018-04-28 19:15:48 -04009986#endif
Thierry FOURNIER5bf77322017-02-25 12:45:22 +01009987 { "ssl_fc_cipherlist_bin", smp_fetch_ssl_fc_cl_bin, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9988 { "ssl_fc_cipherlist_hex", smp_fetch_ssl_fc_cl_hex, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
9989 { "ssl_fc_cipherlist_str", smp_fetch_ssl_fc_cl_str, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
9990 { "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 +02009991 { NULL, NULL, 0, 0, 0 },
9992}};
9993
Willy Tarreau0108d902018-11-25 19:14:37 +01009994INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords);
9995
Willy Tarreau7875d092012-09-10 08:20:03 +02009996/* Note: must not be declared <const> as its list will be overwritten.
9997 * Please take care of keeping this list alphabetically sorted.
9998 */
Willy Tarreaudc13c112013-06-21 23:16:39 +02009999static struct acl_kw_list acl_kws = {ILH, {
Thierry FOURNIERc5a4e982014-03-05 16:07:08 +010010000 { "ssl_fc_sni_end", "ssl_fc_sni", PAT_MATCH_END },
10001 { "ssl_fc_sni_reg", "ssl_fc_sni", PAT_MATCH_REG },
Willy Tarreau8ed669b2013-01-11 15:49:37 +010010002 { /* END */ },
Willy Tarreau7875d092012-09-10 08:20:03 +020010003}};
10004
Willy Tarreau0108d902018-11-25 19:14:37 +010010005INITCALL1(STG_REGISTER, acl_register_keywords, &acl_kws);
10006
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010007/* Note: must not be declared <const> as its list will be overwritten.
10008 * Please take care of keeping this list alphabetically sorted, doing so helps
10009 * all code contributors.
10010 * Optional keywords are also declared with a NULL ->parse() function so that
10011 * the config parser can report an appropriate error when a known keyword was
10012 * not enabled.
10013 */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010014static struct ssl_bind_kw ssl_bind_kws[] = {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010015 { "allow-0rtt", ssl_bind_parse_allow_0rtt, 0 }, /* allow 0-RTT */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010016 { "alpn", ssl_bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10017 { "ca-file", ssl_bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10018 { "ciphers", ssl_bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010019#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010020 { "ciphersuites", ssl_bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10021#endif
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010022 { "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 +010010023 { "curves", ssl_bind_parse_curves, 1 }, /* set SSL curve suite */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010024 { "ecdhe", ssl_bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010025 { "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 +010010026 { "npn", ssl_bind_parse_npn, 1 }, /* set NPN supported protocols */
Emmanuel Hocdetdf701a22017-05-18 12:46:50 +020010027 { "ssl-min-ver", ssl_bind_parse_tls_method_minmax,1 }, /* minimum version */
10028 { "ssl-max-ver", ssl_bind_parse_tls_method_minmax,1 }, /* maximum version */
Emmanuel Hocdet98263292016-12-29 18:26:15 +010010029 { "verify", ssl_bind_parse_verify, 1 }, /* set SSL verify method */
10030 { NULL, NULL, 0 },
10031};
10032
Willy Tarreau0108d902018-11-25 19:14:37 +010010033/* no initcall for ssl_bind_kws, these ones are parsed in the parser loop */
10034
Willy Tarreau51fb7652012-09-18 18:24:39 +020010035static struct bind_kw_list bind_kws = { "SSL", { }, {
Olivier Houchardc2aae742017-09-22 18:26:28 +020010036 { "allow-0rtt", bind_parse_allow_0rtt, 0 }, /* Allow 0RTT */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010037 { "alpn", bind_parse_alpn, 1 }, /* set ALPN supported protocols */
10038 { "ca-file", bind_parse_ca_file, 1 }, /* set CAfile to process verify on client cert */
10039 { "ca-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ignore on verify depth > 0 */
10040 { "ca-sign-file", bind_parse_ca_sign_file, 1 }, /* set CAFile used to generate and sign server certs */
10041 { "ca-sign-pass", bind_parse_ca_sign_pass, 1 }, /* set CAKey passphrase */
10042 { "ciphers", bind_parse_ciphers, 1 }, /* set SSL cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010043#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010044 { "ciphersuites", bind_parse_ciphersuites, 1 }, /* set TLS 1.3 cipher suite */
10045#endif
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010046 { "crl-file", bind_parse_crl_file, 1 }, /* set certificat revocation list file use on client cert verify */
10047 { "crt", bind_parse_crt, 1 }, /* load SSL certificates from this location */
10048 { "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set error IDs to ingore on verify depth == 0 */
10049 { "crt-list", bind_parse_crt_list, 1 }, /* load a list of crt from this location */
10050 { "curves", bind_parse_curves, 1 }, /* set SSL curve suite */
10051 { "ecdhe", bind_parse_ecdhe, 1 }, /* defines named curve for elliptic curve Diffie-Hellman */
10052 { "force-sslv3", bind_parse_tls_method_options, 0 }, /* force SSLv3 */
10053 { "force-tlsv10", bind_parse_tls_method_options, 0 }, /* force TLSv10 */
10054 { "force-tlsv11", bind_parse_tls_method_options, 0 }, /* force TLSv11 */
10055 { "force-tlsv12", bind_parse_tls_method_options, 0 }, /* force TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010056 { "force-tlsv13", bind_parse_tls_method_options, 0 }, /* force TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010057 { "generate-certificates", bind_parse_generate_certs, 0 }, /* enable the server certificates generation */
Emmanuel Hocdet174dfe52017-07-28 15:01:05 +020010058 { "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 +020010059 { "no-sslv3", bind_parse_tls_method_options, 0 }, /* disable SSLv3 */
10060 { "no-tlsv10", bind_parse_tls_method_options, 0 }, /* disable TLSv10 */
10061 { "no-tlsv11", bind_parse_tls_method_options, 0 }, /* disable TLSv11 */
10062 { "no-tlsv12", bind_parse_tls_method_options, 0 }, /* disable TLSv12 */
Emmanuel Hocdet42fb9802017-03-30 19:29:39 +020010063 { "no-tlsv13", bind_parse_tls_method_options, 0 }, /* disable TLSv13 */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010064 { "no-tls-tickets", bind_parse_no_tls_tickets, 0 }, /* disable session resumption tickets */
10065 { "ssl", bind_parse_ssl, 0 }, /* enable SSL processing */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010066 { "ssl-min-ver", bind_parse_tls_method_minmax, 1 }, /* minimum version */
10067 { "ssl-max-ver", bind_parse_tls_method_minmax, 1 }, /* maximum version */
Emmanuel Hocdet5db33cb2017-03-30 19:19:37 +020010068 { "strict-sni", bind_parse_strict_sni, 0 }, /* refuse negotiation if sni doesn't match a certificate */
10069 { "tls-ticket-keys", bind_parse_tls_ticket_keys, 1 }, /* set file to load TLS ticket keys from */
10070 { "verify", bind_parse_verify, 1 }, /* set SSL verify method */
10071 { "npn", bind_parse_npn, 1 }, /* set NPN supported protocols */
10072 { "prefer-client-ciphers", bind_parse_pcc, 0 }, /* prefer client ciphers */
Willy Tarreau79eeafa2012-09-14 07:53:05 +020010073 { NULL, NULL, 0 },
10074}};
Emeric Brun46591952012-05-18 15:47:34 +020010075
Willy Tarreau0108d902018-11-25 19:14:37 +010010076INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);
10077
Willy Tarreau92faadf2012-10-10 23:04:25 +020010078/* Note: must not be declared <const> as its list will be overwritten.
10079 * Please take care of keeping this list alphabetically sorted, doing so helps
10080 * all code contributors.
10081 * Optional keywords are also declared with a NULL ->parse() function so that
10082 * the config parser can report an appropriate error when a known keyword was
10083 * not enabled.
10084 */
10085static struct srv_kw_list srv_kws = { "SSL", { }, {
Olivier Houchard522eea72017-11-03 16:27:47 +010010086 { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */
Olivier Houchardc7566002018-11-20 23:33:50 +010010087 { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010088 { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */
Olivier Houchard92150142018-12-21 19:47:01 +010010089 { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */
Olivier Houchard9130a962017-10-17 17:33:43 +020010090 { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010091 { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */
10092 { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010093#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010094 { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */
10095#endif
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010096 { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */
10097 { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */
10098 { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */
10099 { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */
10100 { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */
10101 { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */
10102 { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */
10103 { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */
10104 { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
10105 { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */
10106 { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */
10107 { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */
10108 { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
10109 { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */
10110 { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */
10111 { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */
10112 { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */
10113 { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
Olivier Houchardc7566002018-11-20 23:33:50 +010010114 { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */
Emmanuel Hocdete1c722b2017-03-31 15:02:54 +020010115 { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
10116 { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
10117 { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
10118 { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
10119 { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */
10120 { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */
10121 { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
10122 { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */
10123 { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */
10124 { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */
Willy Tarreau92faadf2012-10-10 23:04:25 +020010125 { NULL, NULL, 0, 0 },
10126}};
10127
Willy Tarreau0108d902018-11-25 19:14:37 +010010128INITCALL1(STG_REGISTER, srv_register_keywords, &srv_kws);
10129
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010130static struct cfg_kw_list cfg_kws = {ILH, {
Willy Tarreau8c3b0fd2016-12-21 22:44:46 +010010131 { CFG_GLOBAL, "ca-base", ssl_parse_global_ca_crt_base },
10132 { CFG_GLOBAL, "crt-base", ssl_parse_global_ca_crt_base },
Willy Tarreau0bea58d2016-12-21 23:17:25 +010010133 { CFG_GLOBAL, "maxsslconn", ssl_parse_global_int },
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010134 { CFG_GLOBAL, "ssl-default-bind-options", ssl_parse_default_bind_options },
10135 { CFG_GLOBAL, "ssl-default-server-options", ssl_parse_default_server_options },
Willy Tarreau14e36a12016-12-21 23:28:13 +010010136#ifndef OPENSSL_NO_DH
10137 { CFG_GLOBAL, "ssl-dh-param-file", ssl_parse_global_dh_param_file },
10138#endif
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010139 { CFG_GLOBAL, "ssl-mode-async", ssl_parse_global_ssl_async },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010140#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010141 { CFG_GLOBAL, "ssl-engine", ssl_parse_global_ssl_engine },
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010142#endif
Willy Tarreau9ceda382016-12-21 23:13:03 +010010143 { CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
10144#ifndef OPENSSL_NO_DH
10145 { CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
10146#endif
10147 { CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
10148 { CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },
10149 { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
10150 { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
Thierry FOURNIER5bf77322017-02-25 12:45:22 +010010151 { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
Willy Tarreauf22e9682016-12-21 23:23:19 +010010152 { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
10153 { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010154#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010155 { CFG_GLOBAL, "ssl-default-bind-ciphersuites", ssl_parse_global_ciphersuites },
10156 { CFG_GLOBAL, "ssl-default-server-ciphersuites", ssl_parse_global_ciphersuites },
10157#endif
Emeric Brun2c86cbf2014-10-30 15:56:50 +010010158 { 0, NULL, NULL },
10159}};
10160
Willy Tarreau0108d902018-11-25 19:14:37 +010010161INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws);
10162
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010163/* Note: must not be declared <const> as its list will be overwritten */
10164static struct sample_conv_kw_list conv_kws = {ILH, {
Willy Tarreau86a394e2019-05-09 14:15:32 +020010165#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL)
Nenad Merdanovicc31499d2019-03-23 11:00:32 +010010166 { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
10167#endif
10168 { NULL, NULL, 0, 0, 0 },
10169}};
10170
10171INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws);
10172
Willy Tarreauf7bc57c2012-10-03 00:19:48 +020010173/* transport-layer operations for SSL sockets */
Willy Tarreaud9f5cca2016-12-22 21:08:52 +010010174static struct xprt_ops ssl_sock = {
Emeric Brun46591952012-05-18 15:47:34 +020010175 .snd_buf = ssl_sock_from_buf,
10176 .rcv_buf = ssl_sock_to_buf,
Olivier Houcharddf357842019-03-21 16:30:07 +010010177 .subscribe = ssl_subscribe,
10178 .unsubscribe = ssl_unsubscribe,
Olivier Houchard5149b592019-05-23 17:47:36 +020010179 .remove_xprt = ssl_remove_xprt,
Olivier Houchard2e055482019-05-27 19:50:12 +020010180 .add_xprt = ssl_add_xprt,
Emeric Brun46591952012-05-18 15:47:34 +020010181 .rcv_pipe = NULL,
10182 .snd_pipe = NULL,
10183 .shutr = NULL,
10184 .shutw = ssl_sock_shutw,
10185 .close = ssl_sock_close,
10186 .init = ssl_sock_init,
Willy Tarreau55d37912016-12-21 23:38:39 +010010187 .prepare_bind_conf = ssl_sock_prepare_bind_conf,
Willy Tarreau795cdab2016-12-22 17:30:54 +010010188 .destroy_bind_conf = ssl_sock_destroy_bind_conf,
Willy Tarreau17d45382016-12-22 21:16:08 +010010189 .prepare_srv = ssl_sock_prepare_srv_ctx,
10190 .destroy_srv = ssl_sock_free_srv_ctx,
Willy Tarreau8743f7e2016-12-04 18:44:29 +010010191 .get_alpn = ssl_sock_get_alpn,
Willy Tarreau8e0bb0a2016-11-24 16:58:12 +010010192 .name = "SSL",
Emeric Brun46591952012-05-18 15:47:34 +020010193};
10194
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010195enum act_return ssl_action_wait_for_hs(struct act_rule *rule, struct proxy *px,
10196 struct session *sess, struct stream *s, int flags)
10197{
10198 struct connection *conn;
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010199 struct conn_stream *cs;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010200
10201 conn = objt_conn(sess->origin);
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010202 cs = objt_cs(s->si[0].end);
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010203
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010204 if (conn && cs) {
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010205 if (conn->flags & (CO_FL_EARLY_SSL_HS | CO_FL_SSL_WAIT_HS)) {
Olivier Houchard6fa63d92017-11-27 18:41:32 +010010206 cs->flags |= CS_FL_WAIT_FOR_HS;
Olivier Houchardccaa7de2017-10-02 11:51:03 +020010207 s->req.flags |= CF_READ_NULL;
10208 return ACT_RET_YIELD;
10209 }
10210 }
10211 return (ACT_RET_CONT);
10212}
10213
10214static enum act_parse_ret ssl_parse_wait_for_hs(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err)
10215{
10216 rule->action_ptr = ssl_action_wait_for_hs;
10217
10218 return ACT_RET_PRS_OK;
10219}
10220
10221static struct action_kw_list http_req_actions = {ILH, {
10222 { "wait-for-handshake", ssl_parse_wait_for_hs },
10223 { /* END */ }
10224}};
10225
Willy Tarreau0108d902018-11-25 19:14:37 +010010226INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_actions);
10227
Willy Tarreau5db847a2019-05-09 14:13:35 +020010228#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010229
10230static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10231{
10232 if (ptr) {
10233 chunk_destroy(ptr);
10234 free(ptr);
10235 }
10236}
10237
10238#endif
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010239static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
10240{
Willy Tarreaubafbe012017-11-24 17:34:44 +010010241 pool_free(pool_head_ssl_capture, ptr);
Emmanuel Hocdetaaee7502017-03-07 18:34:58 +010010242}
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010243
Emeric Brun46591952012-05-18 15:47:34 +020010244__attribute__((constructor))
Willy Tarreau92faadf2012-10-10 23:04:25 +020010245static void __ssl_sock_init(void)
10246{
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010247#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010248 STACK_OF(SSL_COMP)* cm;
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010249 int n;
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010250#endif
Emeric Brun46591952012-05-18 15:47:34 +020010251
Willy Tarreauef934602016-12-22 23:12:01 +010010252 if (global_ssl.listen_default_ciphers)
10253 global_ssl.listen_default_ciphers = strdup(global_ssl.listen_default_ciphers);
10254 if (global_ssl.connect_default_ciphers)
10255 global_ssl.connect_default_ciphers = strdup(global_ssl.connect_default_ciphers);
Emmanuel Hocdet839af572019-05-14 16:27:35 +020010256#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Dirkjan Bussink415150f2018-09-14 11:14:21 +020010257 if (global_ssl.listen_default_ciphersuites)
10258 global_ssl.listen_default_ciphersuites = strdup(global_ssl.listen_default_ciphersuites);
10259 if (global_ssl.connect_default_ciphersuites)
10260 global_ssl.connect_default_ciphersuites = strdup(global_ssl.connect_default_ciphersuites);
10261#endif
Willy Tarreau610f04b2014-02-13 11:36:41 +010010262
Willy Tarreau13e14102016-12-22 20:25:26 +010010263 xprt_register(XPRT_SSL, &ssl_sock);
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010264#if HA_OPENSSL_VERSION_NUMBER < 0x10100000L
Emeric Brun46591952012-05-18 15:47:34 +020010265 SSL_library_init();
Rosen Penev68185952018-12-14 08:47:02 -080010266#endif
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010267#if (!defined(OPENSSL_NO_COMP) && !defined(SSL_OP_NO_COMPRESSION))
Emeric Brun46591952012-05-18 15:47:34 +020010268 cm = SSL_COMP_get_compression_methods();
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010269 n = sk_SSL_COMP_num(cm);
10270 while (n--) {
10271 (void) sk_SSL_COMP_pop(cm);
10272 }
Ilya Shipitsin0590f442019-05-25 19:30:50 +050010273#endif
Ilya Shipitsine242f3d2019-05-25 03:38:14 +050010274
Willy Tarreau5db847a2019-05-09 14:13:35 +020010275#if defined(USE_THREAD) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010276 ssl_locking_init();
10277#endif
Willy Tarreau5db847a2019-05-09 14:13:35 +020010278#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL)
Janusz Dziemidowicz2c701b52015-03-07 23:03:59 +010010279 sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
10280#endif
Thierry FOURNIER28962c92018-06-17 21:37:05 +020010281 ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Thierry FOURNIER16ff0502018-06-17 21:33:01 +020010282 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 +010010283 ssl_pkey_info_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010284#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010285 ENGINE_load_builtin_engines();
Grant Zhangfa6c7ee2017-01-14 01:42:15 +000010286 hap_register_post_check(ssl_check_async_engine_count);
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010287#endif
Willy Tarreaud1c57502016-12-22 22:46:15 +010010288#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
10289 hap_register_post_check(tlskeys_finalize_config);
10290#endif
Willy Tarreau80713382018-11-26 10:19:54 +010010291
10292 global.ssl_session_max_cost = SSL_SESSION_MAX_COST;
10293 global.ssl_handshake_max_cost = SSL_HANDSHAKE_MAX_COST;
10294
10295#ifndef OPENSSL_NO_DH
10296 ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
10297 hap_register_post_deinit(ssl_free_dh);
10298#endif
10299#ifndef OPENSSL_NO_ENGINE
10300 hap_register_post_deinit(ssl_free_engines);
10301#endif
10302 /* Load SSL string for the verbose & debug mode. */
10303 ERR_load_SSL_strings();
Olivier Houcharda8955d52019-04-07 22:00:38 +020010304 ha_meth = BIO_meth_new(0x666, "ha methods");
10305 BIO_meth_set_write(ha_meth, ha_ssl_write);
10306 BIO_meth_set_read(ha_meth, ha_ssl_read);
10307 BIO_meth_set_ctrl(ha_meth, ha_ssl_ctrl);
10308 BIO_meth_set_create(ha_meth, ha_ssl_new);
10309 BIO_meth_set_destroy(ha_meth, ha_ssl_free);
10310 BIO_meth_set_puts(ha_meth, ha_ssl_puts);
10311 BIO_meth_set_gets(ha_meth, ha_ssl_gets);
William Lallemand150bfa82019-09-19 17:12:49 +020010312
10313 HA_SPIN_INIT(&ckch_lock);
Willy Tarreau80713382018-11-26 10:19:54 +010010314}
Willy Tarreaud92aa5c2015-01-15 21:34:39 +010010315
Willy Tarreau80713382018-11-26 10:19:54 +010010316/* Compute and register the version string */
10317static void ssl_register_build_options()
10318{
10319 char *ptr = NULL;
10320 int i;
10321
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010322 memprintf(&ptr, "Built with OpenSSL version : "
10323#ifdef OPENSSL_IS_BORINGSSL
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010324 "BoringSSL");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010325#else /* OPENSSL_IS_BORINGSSL */
10326 OPENSSL_VERSION_TEXT
10327 "\nRunning on OpenSSL version : %s%s",
Rosen Penev68185952018-12-14 08:47:02 -080010328 OpenSSL_version(OPENSSL_VERSION),
Willy Tarreau1d158ab2019-05-09 13:41:45 +020010329 ((OPENSSL_VERSION_NUMBER ^ OpenSSL_version_num()) >> 8) ? " (VERSIONS DIFFER!)" : "");
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010330#endif
10331 memprintf(&ptr, "%s\nOpenSSL library supports TLS extensions : "
Willy Tarreau9a1ab082019-05-09 13:26:41 +020010332#if HA_OPENSSL_VERSION_NUMBER < 0x00907000L
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010333 "no (library version too old)"
10334#elif defined(OPENSSL_NO_TLSEXT)
10335 "no (disabled via OPENSSL_NO_TLSEXT)"
10336#else
10337 "yes"
10338#endif
10339 "", ptr);
10340
10341 memprintf(&ptr, "%s\nOpenSSL library supports SNI : "
10342#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
10343 "yes"
10344#else
10345#ifdef OPENSSL_NO_TLSEXT
10346 "no (because of OPENSSL_NO_TLSEXT)"
10347#else
10348 "no (version might be too old, 0.9.8f min needed)"
10349#endif
10350#endif
10351 "", ptr);
10352
Emmanuel Hocdetf80bc242017-07-12 14:25:38 +020010353 memprintf(&ptr, "%s\nOpenSSL library supports :", ptr);
10354 for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
10355 if (methodVersions[i].option)
10356 memprintf(&ptr, "%s %s", ptr, methodVersions[i].name);
Emmanuel Hocdet50e25e12017-03-24 15:20:03 +010010357
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010358 hap_register_build_opts(ptr, 1);
Willy Tarreau80713382018-11-26 10:19:54 +010010359}
Willy Tarreauc2c0b612016-12-21 19:23:20 +010010360
Willy Tarreau80713382018-11-26 10:19:54 +010010361INITCALL0(STG_REGISTER, ssl_register_build_options);
Remi Gacogne4f902b82015-05-28 16:23:00 +020010362
Emeric Brun46591952012-05-18 15:47:34 +020010363
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010364#ifndef OPENSSL_NO_ENGINE
Grant Zhang872f9c22017-01-21 01:10:18 +000010365void ssl_free_engines(void) {
10366 struct ssl_engine_list *wl, *wlb;
10367 /* free up engine list */
10368 list_for_each_entry_safe(wl, wlb, &openssl_engines, list) {
10369 ENGINE_finish(wl->e);
10370 ENGINE_free(wl->e);
10371 LIST_DEL(&wl->list);
10372 free(wl);
10373 }
10374}
Emmanuel Hocdet9ac143b2017-05-29 14:36:20 +020010375#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +020010376
Remi Gacogned3a23c32015-05-28 16:39:47 +020010377#ifndef OPENSSL_NO_DH
Grant Zhang872f9c22017-01-21 01:10:18 +000010378void ssl_free_dh(void) {
10379 if (local_dh_1024) {
10380 DH_free(local_dh_1024);
10381 local_dh_1024 = NULL;
10382 }
10383 if (local_dh_2048) {
10384 DH_free(local_dh_2048);
10385 local_dh_2048 = NULL;
10386 }
10387 if (local_dh_4096) {
10388 DH_free(local_dh_4096);
10389 local_dh_4096 = NULL;
10390 }
Remi Gacogne47783ef2015-05-29 15:53:22 +020010391 if (global_dh) {
10392 DH_free(global_dh);
10393 global_dh = NULL;
10394 }
Grant Zhang872f9c22017-01-21 01:10:18 +000010395}
10396#endif
10397
10398__attribute__((destructor))
10399static void __ssl_sock_deinit(void)
10400{
10401#if (defined SSL_CTRL_SET_TLSEXT_HOSTNAME && !defined SSL_NO_GENERATE_CERTIFICATES)
Emeric Brun821bb9b2017-06-15 16:37:39 +020010402 if (ssl_ctx_lru_tree) {
10403 lru64_destroy(ssl_ctx_lru_tree);
Christopher Faulet2a944ee2017-11-07 10:42:54 +010010404 HA_RWLOCK_DESTROY(&ssl_ctx_lru_rwlock);
Emeric Brun821bb9b2017-06-15 16:37:39 +020010405 }
Remi Gacogned3a23c32015-05-28 16:39:47 +020010406#endif
10407
Willy Tarreau5db847a2019-05-09 14:13:35 +020010408#if (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010409 ERR_remove_state(0);
10410 ERR_free_strings();
10411
10412 EVP_cleanup();
Rosen Penev68185952018-12-14 08:47:02 -080010413#endif
Remi Gacogned3a23c32015-05-28 16:39:47 +020010414
Willy Tarreau5db847a2019-05-09 14:13:35 +020010415#if (HA_OPENSSL_VERSION_NUMBER >= 0x00907000L) && (HA_OPENSSL_VERSION_NUMBER < 0x10100000L)
Remi Gacogned3a23c32015-05-28 16:39:47 +020010416 CRYPTO_cleanup_all_ex_data();
10417#endif
Olivier Houcharda8955d52019-04-07 22:00:38 +020010418 BIO_meth_free(ha_meth);
Remi Gacogned3a23c32015-05-28 16:39:47 +020010419}
10420
10421
Emeric Brun46591952012-05-18 15:47:34 +020010422/*
10423 * Local variables:
10424 * c-indent-level: 8
10425 * c-basic-offset: 8
10426 * End:
10427 */